What is Eureka in microservices

Stefan Janser 3

An important component of a microservice infrastructure is the service registry, which combines services, their instances and locations in a data structure. The article shows how the Netflix project Eureka works using a simple example.

Netflix generates the highest downstream bandwidth in the US at over 35 percent, far more than YouTube (15%) and Facebook (6%) combined. When the monolithic architecture was no longer able to cope with the growing traffic, the streaming service converted it into a system made up of more than a hundred microservices between 2008 and 2012. Since then, Netflix has been relying on fine-grained, loosely coupled services. The company has developed technical components and libraries in order to monitor the multitude of services and to meet the high requirements for reliability and scalability. They form the infrastructure for the Netflix services and implement common patterns for distributed systems.

The components have to prove their quality in the Netflix environment on a daily basis in a complex, load-intensive scenario. Thanks to sophisticated monitoring, Netflix quickly detects errors and weaknesses in the components and fixes them - the quality of the components is correspondingly high. They are made available as free software in the Netflix Open Source Software Center (Netflix OSS). Spring Cloud Netflix, a sub-project of Spring Cloud, uses six services from the Netflix OSS:

  • Eureka: Service registry and mid-tier load balancer
  • Hystrix: Library that isolates errors when accessing external services and thus increases the reliability in a distributed system (circuit breaker)
  • Ribbon: Library for interprocess communication with built-in software load distributor
  • Archaius: Library for configuration management, based on Apache Commons Configuration and expands the project for cloud use
  • Zuul: Edge service for dynamic routing, monitoring, security, failure safety and a lot more
  • Feign: Library that simplifies the writing of HTTP clients

An important component of a microservice infrastructure is the service registry, which combines services, their instances and locations in a data structure. The article shows how Eureka works using a simple example. Basic knowledge of Spring Boot makes sense because Spring Cloud is based on it. There is an introduction at spring.io, for example.

Register microservices with Spring Cloud Netflix

With Eureka, microservices are registered under a logical name, after which they can be addressed using this name. This means that services can run dynamically on different instances without the user having to know the actual URL of the service.

Eureka manages the services dynamically: the project detects when a service is no longer available and removes it from the registry. In addition, several instances of a service can register under the same logical name; Eureka takes over the load distribution between the instances. Services are found through the interaction between the Eureka client and server. The server collects the information about the registered services. For greater reliability, it is usually operated redundantly in the productive environment. The redundant instances synchronize their service registries with one another. The Eureka client is a library for communication with the Eureka server.

The example in this tutorial consists of three microservices (see Fig. 1):

  • the Eureka server, which provides the service registry,
  • the HELLOWORLD SERVICE, via which the Eureka client registers its service with the Eureka server,
  • and the discovery client, which receives the HELLOWORLD SERVICE via the Eureka server and calls it up.

To register a service, the Eureka client sends a registration with a logical name and the corresponding URL to the Eureka server (register). Then it sends a so-called heartbeat every 30 seconds as a sign of life to the server (Renew). If there is no heartbeat, the Eureka server automatically deletes the instance in the directory (Cancel). The client updates the registry at regular intervals with all registered services (Get Registry). When calling up another service, the client can determine the URL of the service to be called based on the logical name and thus send a remote call to the service.

Installation, example

Set up the service registry with the Eureka server

The Eureka server is a Spring Boot service enriched with special annotations. It collects information about registered services. First, the necessary libraries are in the Maven pom.xml as dependencies. In addition to the reference to the parent POM (Project Object Model) spring-cloud-starter-parent need the artifacts spring-cloud-starter-eureka-server, spring-boot-starter-security and spring-cloud-starter-hystrix be integrated.

<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>1.0.1.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

The Eureka server is in the file application.yml configured:

server:
port: 8761
security:
basic:
enabled: false

eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
waitTimeInMsWhenSyncEmpty: 0

The first step defines that the Eureka server is running on port 8761. The second turns off some options and simplifies the example configuration: registerWithEureka: false and fetchRegistry: false deactivate, for example, the possibility of replication between several Eureka servers in standalone mode.

After starting, Eureka gives the clients a five-minute time window for registration; in the example the waiting time is with waitTimeInMsWhenSyncEmpty: 0 set to "zero". The Eureka server is protected by default so that only authorized entities can access it. For the example configuration, the protection mechanism can be used with security: basic: enabled: false turn off.

The service still needs a main method to start; she will be in class EurekaServerApplication.java offered. Through the annotation @EnableEurekaServer Spring Cloud recognizes that it is a Eureka server and starts the corresponding service.

package com.maibornwolff.server;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

import java.io.IOException;

@SpringCloudApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

Now the Eureka server works, on which a service can register. The next step is to integrate the Eureka client in the HELLOWORLD SERVICE.

Create the HelloWorld service

The HelloWorld service is also a Spring Boot service that contains a Eureka client based on special annotations. In addition to the reference to the parent POM, the service is required spring-cloud-starter-parent the artifacts spring-cloud-starter-eureka and spring-boot-starter-web. The latter is necessary to create a REST service.

<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>1.0.1.RELEASE</version>
<relativePath/>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

</dependencies>

In the file application.yml two pieces of information are set: the URL of the Eureka server and the port on which the Hello World service is available.

eureka:
client:
serviceUrl:
defaultZone: http: // localhost: 8761 / eureka /

server:
port: 8888

The application name that you find in the file bootstrap.yml is also the logical name of the microservice - in this example helloWorld service:

jump:
application:
name: helloWorld-service

The next step implements the REST service. Under the resource Hello gives the service "Hello cloudy world" back in response.

HelloController.java

package com.maibornwolff.client;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@RequestMapping ("/ hello")
public string hello () {
return "Hello cloudy world";
}

}

In order for the REST service to be registered under its logical application name, in addition to the Spring Boot annotations @SpringBootApplication and @EnableAutoConfiguration the annotation @EnableEurekaClient specify.

HelloWorldServiceApplication.java

package com.maibornwolff.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableAutoConfiguration
@EnableEurekaClient
public class HelloWorldServiceApplication {

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

}

Once started, the service registers on the Eureka server. This can be done in the web GUI of the Eureka server (http: // localhost: 8761) comprehend. The HELLOWORLD SERVICE is now visible under the list of registered instances (see Fig. 2).

Example, part 2

Use the service via a discovery client

Developers can use the registered service, for example, in a command line application, here with the name Discovery Client. The application calls the HELLOWORLD-SERVICE using its logical name and outputs the result on the command line. To do this, the Discovery client must also be annotated as a Eureka client. It therefore needs the following dependencies.

<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>1.0.1.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

To implement the discovery client, developers need the Spring Boot annotation @SpringBootApplication and the spring cloud annotation @EnableEurekaClient. So that the SpringApplicationBuilder knows that it is a command line application, specify the following:

new SpringApplicationBuilder (DiscoveryClientApplication.class)
.web (false)
.run (args);

This will make the runMethod of the class RestTemplateExample called at startup. It implements the CommandLineRunner. All the magic of service binding is done in the Spring RestTemplate. Here you use the logical name "helloWorld-service" in the URL instead of the actual URL "localhost: 8888".

DiscoveryClientApplication.java

package com.maibornwolff.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
public class DiscoveryClientApplication {
public static void main (String [] args) {
new SpringApplicationBuilder (DiscoveryClientApplication.class)
.web (false)
.run (args);
}
}

@Component
class RestTemplateExample implements CommandLineRunner {

@Autowired
private RestTemplate restTemplate;

@Override
public void run (String ... strings) throws Exception {
// use the "smart" Eureka-aware RestTemplate
String exchange =
this.restTemplate.getForObject (
"http: // helloWorld-service / hello",
String.class);

System.out.println (exchange);
}

}

Test: Hello cloudy world

When the Discovery client starts, the Eureka client queries the service registry of the Eureka server. Before the actual REST call, the client checks whether a registered service exists under the logical name and replaces it with the physical endpoint with which the REST call is made.

The output of the console is, as defined in the implementation of the REST service, Hello cloudy world. This shows that the service registration is working and that the services can be found under their logical name.

As a small extension, a further instance of the Hello World service can be started by adjusting the port. The Eureka client now ensures round robin load balancing between the two services. If one of the services is terminated, the Eureka server recognizes this and only forwards the requests to the active service.

Conclusion

Spring Cloud Netflix offers many high quality components for developing to operate a microservice architecture. Unfortunately, the documentation does not always keep up with the fast release cycles in the project. Many configuration options are not documented and can only be discovered by analyzing the source code. The Spring Cloud contributors consequently define the documentation as an important goal on the roadmap for the next versions.

This article makes a small contribution to this goal: As shown, a functioning service registry for microservices can be set up in just a few minutes with the Eureka component of Spring Cloud Netflix. (ane)

Stefan Janser
works as Senior Software Engineer at MaibornWolff. The qualified computer scientist deals with the development and integration of large distributed systems with cloud and web technologies.

3 comments