Spring Cloud Microservices — Part 1 — Service Discovery with Netflix Eureka

Okan Ardıç
4 min readOct 12, 2022

--

Photo by Markus Winkler on Unsplash

Introduction

To see the complete list of Spring Cloud Microservices tutorial series, you can check this link.

First of all, let’s understand what service discovery is. In a traditional service environment, each service is accessible via hostname / IP and assigned port. When there are multiple services, it gets complicated to configure and manage all these services, where they are located or how to call them. Including service replicas for failover or load balancing, it gets even harder to manage all these services. Eureka is developed by Netflix to cope with these issues by helping to build resilient applications with service discovery, load balancing and failover features.

Eureka Server is a discovery server where each client application registers itself. It works like an internal DNS providing the clients to call services by their DNS addresses. It also provides load balancing that distributes the traffic between the service replicas in round-robin fashion. So, there will be no need to know the IP/port information for the services, and manual configuration is not needed when you scale in or out your services. Let’s clarify one thing here; manually accessing the service via service name (http://my-service/) is still not possible (unless you define the service name as a hostname in your host machine). The point here is that, if you have integration with clients such as OpenFeign, API Gateway etc. which can communicate with the discovery server, then they will be able to retrieve the list of services that are associated to the given service name.

1- Starting Discovery Server

Now, let’s start with a new project, and follow the steps below to start a Eureka Server:

1- Add spring-cloud-starter-netflix-eureka-server dependency in your classpath.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2- Add @EnableEurekaServer annotation to one of your @Configuration classes like the example below:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}

3- Configure service port and discovery settings in application.yml like below:

server:
port: 8761
spring:
application:
name: eureka
eureka:
client:
register-with-eureka: false
fetch-registry: false

Set the value of eureka.client.register-with-eureka and eureka.client.fetch-registry properties to false to disable service discovery for the service, since it would not be needed for the discovery server itself.

4- Start the application and navigate to http://localhost:8761 to see Eureka homepage:

Eureka homepage

All registered services will be listed as well as their statuses and number of instances per service. Above image is for reference only, as it lists some registered services already. So, you should not be seeing any services in the list at the beginning. Now let’s continue to see how the clients register themselves to the discovery server.

2- Registering Services on the Discovery Server

1- Add the following dependencies to the classpath on the target services’ pom.xml files (in our example we have User Service, Product Service and Order Service):

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

spring-boot-starter-actuator dependency provides endpoints to gather information about application health, metrics, threads etc. which are useful to monitor the application.

2- Add @EnableEurekaClient annotation to one of your @Configuration classes like the example below:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}

3- Configure application.yml file to define the service name and discovery server settings:

server:
port: 8080
spring:
application:
name: user-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
instance:
hostname: localhost

The property spring.application.name will be the application name registered on Eureka server. If you have multiple replicas of the same service, make sure the same value is assigned to that property, so incoming requests can be automatically load-balanced. Also make sure this value is unique accross different services, otherwise discovery server will think of these services as identical and load-balance all requests between the services sharing the same spring.application.name value. This might result in 404 errors, if the requests are forwarded to the wrong services.

The value of eureka.client.serviceUrl.defaultZone points to the discovery server (Eureka in our case).

4- Start all services and check Eureka homepage for the registered services.

Summary

Netflix Eureka provides a discovery server to register services and simplify accessing these services without having to know the actual IP/port information of these services.

You can continue with the next tutorial to see how a discovery server can be used with an API Gateway.

Next Tutorial: Integrating API Gateway

Source Code

You can download the complete source code of this tutorial series from this link.

References

https://cloud.spring.io/spring-cloud-netflix/multi/multi__service_discovery_eureka_clients.html

--

--