Dynamically registering and finding services with Eureka

At a fundamental level, taking one big application (like we've built so far) and splitting it up into two or more microservices requires that the two systems communicate with each other. And to communicate, these systems need to find each other. This is known as service discovery.

The Netflix engineering team built a tool for this called Eureka, and open sourced it. Eureka provides the means for microservices to power up, advertise their existence, and shutdown as well. It supports multiple copies of the same service registering themselves, and allows multiple instances of Eureka to register with each other to develop a highly available service registry.

Standing up a Eureka Server is quite simple. We simply have to create a new application at http://start.spring.io:

Yes, that's correct. We create an entirely separate Spring Boot application using the Spring Initializr, apart from our functional application. And in the preceding screenshot, the arrows point out that we are calling it learning-spring-boot-eureka-server while also adding a single dependency, Eureka Server. This application will be dedicated to providing our microservices with a service registry.

If we peek at our Eureka Server's build file, we'll find a slim list of dependencies toward the bottom:

    dependencies { 
      compile('org.springframework.cloud:spring-cloud-starter-eureka-
server') } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-
dependencies:${springCloudVersion}" } }

This short list has but one dependency--spring-cloud-starter-eureka-server. Following it is the same Spring Cloud Bill of Materials (BOM) used to provide the proper versions of the Spring Cloud components.

Toward the top of the build file, we can see the exact versions of both Spring Boot and Spring Cloud:

    buildscript { 
      ext { 
        springBootVersion = '2.0.0.M5' 
        springCloudVersion = 'Finchley.M3' 
      } 
      ... 
    } 
Spring Cloud's Finchley release train, also mentioned in the previous chapter, is the version compatible with Spring Boot 2.0.

With that in place, the only code we must write is shown here:

    @SpringBootApplication 
    @EnableEurekaServer 
    public class LearningSpringBootEurekaServerApplication { 
 
      public static void main(String[] args) { 
        SpringApplication.run( 
          LearningSpringBootEurekaServerApplication.class); 
      } 
    } 

This preceding simple application can be described as follows:

  • @SpringBootApplication marks this app as a Spring Boot application, which means that it will autoconfigure beans based on the classpath, and load properties as well.
  • @EnableEurekaServer tells Spring Cloud Eureka that we want to run a Eureka Server. It proceeds to configure all the necessary beans to host a service registry.
  • The code inside public static void main is the same as the previous chapters, simply loading the surrounding class.

Before we can launch our Eureka service registry, there are some key settings that must be plugged in. To do so, we need to create a src/main/resources/application.yml file as follows:

    server: 
      port: 8761 
 
    eureka: 
      instance: 
        hostname: localhost 
      client: 
        registerWithEureka: false 
        fetchRegistry: false 
        serviceUrl: 
          defaultZone: 
http://${eureka.instance.hostname}:${server.port}/eureka/

The previous configuration file can be explained in detail as follows:

  • server.port lets us run it on Eureka's standard port of 8761.
  • For a standalone Eureka Server, we have to configure it with a eureka.instance.hostname and a eureka.client.serviceUrl.defaultZone setting. This resolves to http://localhost:8761/eureka, the URI for this standalone version of Eureka. For a multi-node Eureka Server configuration, we would alter this configuration.

Eureka servers are also clients, which means that with multiple instances running, they will send heartbeats to each other, and also registry data. With a standalone instance, we would get bombarded with log messages about failing to reach peers unless we disable the Eureka server from being a client via eureka.client.registerWithEureka=false and eureka.client.fetchRegistry=false (as we just did).

To run things in a more resilient mode, we could run two instances, each with a different Spring profile (peer1 and peer2) with the following configuration:

    --- 
    spring: 
      profiles: peer1 
    eureka: 
      instance: 
        hostname: peer1 
      client: 
        serviceUrl: 
          defaultZone: http://peer2/eureka/ 
 
    --- 
    spring: 
      profiles: peer2 
    eureka: 
      instance: 
        hostname: peer2 
      client: 
        serviceUrl: 
          defaultZone: http://peer1/eureka/ 

spring.profiles, in a YAML file with the triple-dash separators, lets us put multiple profiles in the same application.yml configuration file. To launch an application with a given profile, we merely need to run it with spring.profiles.active=peer1 or SPRING_PROFILES_ACTIVE=peer1. As stated, this configuration file has two profiles, peer1 and peer2.

Assuming we launched two separate copies of our Eureka Server, each on a different port running each profile, they would seek each other out, register as clients to each other, send heartbeats, and synchronize their registry data. It's left as an exercise for the reader to spin up a pair of Eureka Servers.

Going back to the original configuration file we wrote, we can now run LearningSpringBootEurekaServerApplication. With this service running in the background, we can now embark on converting our previous monolith into a set of microservices.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset