Skip to content

Spring Cloud Netflix Eureka Server-Client#

What Is Netflix Eureka Server?#

  • Eureka Server is an application that holds the information about all client-service applications. Every Micro service will register into the Eureka server and Eureka server knows all the client applications running on each port and IP address. Eureka Server is also known as Discovery Server.
  • More information

Netflix Eureka Server Dependencies#

  • Note Netflix Eureka Server dependencies require you to add Spring Cloud dependency first as mentioned in Spring Cloud Introduction. So maybe you have to add the dependency below first.
pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<properties>
    <spring.cloud-version>2021.0.0</spring.cloud-version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • Then to use Netflix Eureka Server in your Spring Boot application. You will need to add some dependencies as below
pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<dependencies>

    <!-- ...other dependencies -->

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

    <dependency>  
         <groupId>com.google.code.gson</groupId>  
         <artifactId>gson</artifactId>  
         <version>2.8.9</version>  
    </dependency>

    <!-- ...other dependencies -->

</dependencies>

Configure Netflix Eureka Server#

  • Now, you will need to add annotation @EnableEurekaServer into your main class as below.
ServerApplication.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.eureka.server;  

import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;  

@SpringBootApplication  
@EnableEurekaServer  
public class ServerApplication {  

   public static void main(String[] args) {  
      SpringApplication.run(ServerApplication.class, args);  
   }  

}
  • Then In your application.yml. Let's add some configuration. The details of configuration are put in the comments.
application.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#server run at port 8761
server:
  port: 8761

spring:
  application:
    #application name
    name: eureka-server

eureka:
  client:
    #self register is false
    register-with-eureka: false
    #self fetch registry is false
    fetch-registry: false

TESTING#

  • Now, let's start your Spring Boot service and go to access to http://localhost:8761 to check the eureka service has run successfully.

 #zoom

  • Then you can check your service log and you can see the url as in the image below which will be used for client to register to eureka server (http://localhost:8761/eureka/)

 #zoom

What Is Netflix Eureka Client?#

  • Eureka Client: it can be a microservice that is ready to work so it registers itself to the Eureka server e.g. an API for some app, or some application that goes to the server and asks for directions to a specific microservice.

Netflix Eureka Client Dependencies#

  • Like Eureka Server, you also need to add a dependency for Spring Cloud.
  • Note Netflix Eureka Server dependencies require you to add Spring Cloud dependency first as mentioned in Spring Cloud Introduction. So maybe you have to add the dependency below first.
pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<properties>
    <spring.cloud-version>2021.0.0</spring.cloud-version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • Then to use Netflix Eureka Client in your Spring Boot application. You will need to add some dependencies as below
pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<dependencies>

    <!-- ...other dependencies -->

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

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.13.1</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.13.1</version>
    </dependency>

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.9</version>
    </dependency>

    <!-- ...other dependencies -->

</dependencies>

Configure Netflix Eureka Client#

  • Now, Let's add annotation @EnableDiscoveryClient into main class.
BffApplication.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.application.bff;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class BffApplication {

    public static void main(String[] args) {
        SpringApplication.run(BffApplication.class, args);
    }

}
  • Then add some configuration in application.yml as below to connect to Eureka Server. The property “eureka.client.serviceUrl.defaultZone” will be the url for register of eureka server.
application.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#service run at port 9090
server:
  port: 9090

spring:
  application:
    #service name which will be showed on eureka server dashboard
    name: application-bff-service
  #Enable Spring Cloud Discovery
  cloud:
    discovery:
      enabled: true

#register this service to eureka server by url
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

Testing#

  • Now, let's start your Spring Boot service of Eureka Client then recheck the eureka server dashboard and you can see client registered successfully.

 #zoom

How Do They Work?#

  • From these sections above, you will know how to create Eureka Server, Eureka Client and connect Client to Server. So in this section we will find how do they work behind the scene.

Eureka Client Instance Statuses#

  • By default, Eureka client starts in STARTING state which gives the instance a chance to do application-specific initializations, before it can serve traffic.
  • The application then can explicitly put the instance for traffic, by turning the instance status to UP.
  • The application can also register health check callbacks which can change the instance status to DOWN optionally when it can not start successfully.
  • At Netflix, we also use the OUT_OF_SERVICE status, primarily for taking an instance out of traffic. It is used for easy rollback of deployments of new revisions in case of problems. Most applications create a new ASG(Auto Scaling Group) for a new revision and the traffic gets routed the new ASGs. In the case of problems, rolling back a revision is just a matter of turning off the traffic by setting all instances in the ASG to OUT_OF_SERVICE.

Eureka Server - Eureka Client Interactions#

  • The Eureka client interacts with the server the following ways.
  • Register: Eureka client registers the information about the running instance to the Eureka server. Registration happens on first heartbeat (after 30 seconds).

  • Renew: Eureka client needs to renew the lease by sending heartbeats every 30 seconds. The renewal informs the Eureka server that the instance is still alive. If the server hasn't seen a renewal for 90 seconds, it removes the instance out of its registry. It is advisable not to change the renewal interval since the server uses that information to determine if there is a wide spread problem with the client to server communication.

  • Fetch Registry: Eureka clients fetches the registry information from the server and caches it locally. After that, the clients use that information to find other services. This information is updated periodically (every 30 seconds) by getting the delta updates between the last fetch cycle and the current one. The delta information is held longer (for about 3 mins) in the server, hence the delta fetches may return the same instances again. The Eureka client automatically handles the duplicate information.

 #zoom

  • After getting the deltas, Eureka client reconciles the information with the server by comparing the instance counts returned by the server and if the information does not match for some reason, the whole registry information is fetched again. Eureka server caches the compressed payload of the deltas, whole registry and also per application as well as the uncompressed information of the same. The payload also supports both JSON/XML formats. Eureka client gets the information in compressed JSON format using jersey apache client.
  • You can visit method fetchRegistry() in class com.netflix.discovery.DiscoveryClient to see the Eureka Client fetches the registry information from Eureka Server. This method will be called every 30s.
DiscoveryClient.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    /**
     * Fetches the registry information.
     *
     * <p>
     * This method tries to get only deltas after the first fetch unless there
     * is an issue in reconciling eureka server and client registry information.
     * </p>
     *
     * @param forceFullRegistryFetch Forces a full registry fetch.
     *
     * @return true if the registry was fetched
     */
    private boolean fetchRegistry(boolean forceFullRegistryFetch) {
        Stopwatch tracer = FETCH_REGISTRY_TIMER.start();

        try {
            // If the delta is disabled or if it is the first time, get all
            // applications
            Applications applications = getApplications();

            if (clientConfig.shouldDisableDelta()
                    || (!Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress()))
                    || forceFullRegistryFetch
                    || (applications == null)
                    || (applications.getRegisteredApplications().size() == 0)
                    || (applications.getVersion() == -1)) //Client application does not have latest library supporting delta
            {
                logger.info("Disable delta property : {}", clientConfig.shouldDisableDelta());
                logger.info("Single vip registry refresh property : {}", clientConfig.getRegistryRefreshSingleVipAddress());
                logger.info("Force full registry fetch : {}", forceFullRegistryFetch);
                logger.info("Application is null : {}", (applications == null));
                logger.info("Registered Applications size is zero : {}",
                        (applications.getRegisteredApplications().size() == 0));
                logger.info("Application version is -1: {}", (applications.getVersion() == -1));
                getAndStoreFullRegistry();
            } else {
                getAndUpdateDelta(applications);
            }
            applications.setAppsHashCode(applications.getReconcileHashCode());
            logTotalInstances();
        } catch (Throwable e) {
            logger.info(PREFIX + "{} - was unable to refresh its cache! This periodic background refresh will be retried in {} seconds. status = {} stacktrace = {}",
                    appPathIdentifier, clientConfig.getRegistryFetchIntervalSeconds(), e.getMessage(), ExceptionUtils.getStackTrace(e));
            return false;
        } finally {
            if (tracer != null) {
                tracer.stop();
            }
        }

        // Notify about cache refresh before updating the instance remote status
        onCacheRefreshed();

        // Update remote status based on refreshed data held in the cache
        updateInstanceRemoteStatus();

        // registry was fetched successfully, so return true
        return true;
    }
  • Cancel: Eureka client sends a cancel request to Eureka server on shutdown. This removes the instance from the server's instance registry thereby effectively taking the instance out of traffic.
    • This is done when the Eureka client shuts down and the application should make sure to call the following during its shutdown.

Additional Information#

  • Time Lag: All operations from Eureka client may take some time to reflect in the Eureka servers and subsequently in other Eureka clients. This is because of the caching of the payload on the eureka server which is refreshed periodically to reflect new information. Eureka clients also fetch deltas periodically. Hence, it may take up to 2 mins for changes to propagate to all Eureka clients.
  • Communication mechanism: By default, Eureka clients use Jersey and Jackson along with JSON payload to communicate with Eureka Server.

See Also#

References#