//

Spring Cloud Service Discovery with Dynamic Metadata

8.1.2018 | 2 minutes of reading time

Spring Cloud Service Discovery

If you are running applications consisting of a lot of microservices depending on each other, you are probably using some kind of service registry. Spring Cloud offers a set of starters for interacting with the most common service registries.

For the rest of this article, let’s assume you are familiar with the core Spring Boot ecosystem.

In our example we will use the service registry Eureka from Netflix running on localhost:8761. We will run two services service-1 on port 8080 and service-2 on port 8081 both implemented with Spring Boot. In order to register itself and look up others services, each service includes the following starter as a build dependency:

1<dependencyManagement>
2  <dependencies>
3    <dependency>
4      <groupId>org.springframework.cloud</groupId>
5      <artifactId>spring-cloud-dependencies</artifactId>
6      <version>Dalston.SR4</version>
7      <type>pom</type>
8      <scope>import</scope>
9    </dependency>
10  </dependencies>
11</dependencyManagement>
12...
13<dependency>
14  <groupId>org.springframework.cloud</groupId>
15  <artifactId>spring-cloud-starter-eureka</artifactId>
16</dependency>
17

Each service has to configure its unique name and where the Eureka server is located. We will use the YAML format in src/resources/application.yml:

1spring:
2  application:
3    name: service-1
4
5eureka:
6  client:
7    serviceUrl:
8      defaultZone: http://localhost:8761/eureka
9

The configuration of service-2 will look similar.

Service Discovery

The implementation of service-2 contains a simple REST controller to access the service registry:

1@RestController
2public class RegistryLookup {
3 
4   @Autowired
5   private DiscoveryClient discoveryClient;
6 
7   @RequestMapping("/lookup/{serviceId}")
8   public List<ServiceInstance> lookup(@PathVariable String serviceId) {
9      return discoveryClient.getInstances(serviceId);
10   }
11 
12}
13

In order to use the DiscoveryClient API, you have to use the annotation @EnableDiscoveryClient somewhere within your configuration classes.

A lookup of service-1 …

1http://localhost:8081/lookup/service-1
2

… yields a lot of information on that service:

1{
2    "host": "SOME.IP.ADDRESS",
3    "port": 8080,
4    "secure": false,
5    "instanceInfo": {
6        "instanceId": "SOME.IP.ADDRESS:service-1:8080",
7        "app": "SERVICE-1",
8        ...
9

This information is used by REST clients like Feign to discover the HTTP endpoint of services by symbolic names like service-1.

Static Service Metadata

Each service can define arbitrary metadata within its configuration. With Eureka, this metadata can be a map of values defined in application.yml:

1eureka:
2  instance:
3    metadata-map:
4      fixed-s1: "value_1"
5

This metadata can be used by clients for various use cases. A service can describe SLAs, quality of data or whatever you want. But this metadata is fixed in a sense that is has to be known at build or deployment time. The latter is the case when you overwrite your Spring environment with JVM or OS environment variables. Anyway, the metadata show up within the lookup http://localhost:8081/lookup/service-1:

1{
2    "host": "localhost",
3    "port": 8080,
4    "uri": "http://localhost:8080",
5    "metadata": {
6        "fixed-s1": "value_1"
7    },
8    "secure": false,
9    "serviceId": "SERVICE-1",
10    ...
11}
12

Dynamic Service Metadata

If a service wants to detect and register its metadata at runtime, you have to use the client API of the service registry in use. With the Eureka client this may look like this:

1@Component
2public class DynamicMetadataReporter {
3 
4   @Autowired
5   private ApplicationInfoManager aim;
6 
7   @PostConstruct
8   public void init() {
9      Map<String, String> map = aim.getInfo().getMetadata();
10      map.put("dynamic-s1", "value_2");
11   }
12}
13

The class ApplicationInfoManager is from the Eureka client API and allows you to dynamically add metadata that shows up if we query the service registry for service-1:

1{
2    "host": "localhost",
3    "port": 8080,
4    "uri": "http://localhost:8080",
5    "metadata": {
6        "dynamic-s1": "value_2",  // dynamic metadata
7        "fixed-s1": "value_1"
8    },
9    "secure": false,
10    "serviceId": "SERVICE-1",
11    ...
12}
13

share post

Likes

0

//

More articles in this subject area\n

Discover exciting further topics and let the codecentric world inspire you.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.