Un guide rapide sur Spring Cloud Consul

1. Vue d'ensemble

Le projet Spring Cloud Consul permet une intégration facile avec Consul pour les applications Spring Boot.

Consul est un outil qui fournit des composants pour résoudre certains des défis les plus courants dans une architecture de micro-services:

  • Service Discovery - pour enregistrer et désenregistrer automatiquement les emplacements réseau des instances de service
  • Vérification de l'état - pour détecter lorsqu'une instance de service est opérationnelle
  • Configuration distribuée - pour garantir que toutes les instances de service utilisent la même configuration

Dans cet article, nous verrons comment nous pouvons configurer une application Spring Boot pour utiliser ces fonctionnalités.

2. Prérequis

Pour commencer, il est recommandé de jeter un coup d'œil à Consul et à toutes ses fonctionnalités.

Dans cet article, nous allons utiliser un agent Consul s'exécutant sur localhost: 8500 . Pour plus d'informations sur l'installation de Consul et l'exécution d'un agent, consultez ce lien.

Tout d'abord, nous devons ajouter la dépendance spring-cloud-starter-consul-all à notre pom.xml :

 org.springframework.cloud spring-cloud-starter-consul-all 1.3.0.RELEASE 

3. Découverte des services

Écrivons notre première application Spring Boot et connectons avec l'agent Consul en cours d'exécution:

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

Par défaut, Spring Boot essaiera de se connecter à l'agent Consul à localhost: 8500 . Pour utiliser d'autres paramètres, nous devons mettre à jour le fichier application.yml :

spring: cloud: consul: host: localhost port: 8500

Ensuite, si nous visitons le site de l'agent Consul dans le navigateur à l' adresse // localhost: 8500 , nous verrons que notre application a été correctement enregistrée dans Consul avec l'identifiant de "$ {spring.application.name}: $ {profils séparés par virgule}: $ {server.port} » .

Pour personnaliser cet identifiant, nous devons mettre à jour la propriété spring.cloud.discovery.instanceId avec une autre expression:

spring: application: name: myApp cloud: consul: discovery: instanceId: ${spring.application.name}:${random.value}

Si nous exécutons à nouveau l'application, nous verrons qu'elle a été enregistrée en utilisant l'identifiant «MyApp» plus une valeur aléatoire. Nous en avons besoin pour exécuter plusieurs instances de notre application sur notre machine locale.

Enfin, pour désactiver la découverte de service, nous devons définir la propriété spring.cloud.consul.discovery.enabled sur false .

3.1. Recherche de services

Notre application est déjà enregistrée dans Consul, mais comment les clients peuvent-ils trouver les points de terminaison du service? Nous avons besoin d'un service client de découverte pour obtenir un service opérationnel et disponible de Consul.

Spring fournit une API DiscoveryClient pour cela , que nous pouvons activer avec l' annotation @EnableDiscoveryClient :

@SpringBootApplication @EnableDiscoveryClient public class DiscoveryClientApplication { // ... }

Ensuite, nous pouvons injecter le bean DiscoveryClient dans notre contrôleur et accéder aux instances:

@RestController public class DiscoveryClientController { @Autowired private DiscoveryClient discoveryClient; public Optional serviceUrl() { return discoveryClient.getInstances("myApp") .stream() .findFirst() .map(si -> si.getUri()); } }

Enfin, nous définirons nos points de terminaison d'application:

@GetMapping("/discoveryClient") public String discoveryPing() throws RestClientException, ServiceUnavailableException { URI service = serviceUrl() .map(s -> s.resolve("/ping")) .orElseThrow(ServiceUnavailableException::new); return restTemplate.getForEntity(service, String.class) .getBody(); } @GetMapping("/ping") public String ping() { return "pong"; }

Le chemin «myApp / ping» est le nom de l'application Spring avec le point de terminaison du service. Consul fournira toutes les applications disponibles nommées «myApp».

4. Vérification de l'état de santé

Consul vérifie périodiquement la santé des points de terminaison de service.

Par défaut, Spring implémente le point de terminaison d'intégrité pour renvoyer 200 OK si l'application est active . Si nous voulons personnaliser le point de terminaison, nous devons mettre à jour l' application.yml:

spring: cloud: consul: discovery: healthCheckPath: /my-health-check healthCheckInterval: 20s

Par conséquent, Consul interrogera le point de terminaison «/ my-health-check» toutes les 20 secondes.

Définissons notre service de vérification de l'état personnalisé pour renvoyer un statut INTERDIT :

@GetMapping("/my-health-check") public ResponseEntity myCustomCheck() { String message = "Testing my healh check function"; return new ResponseEntity(message, HttpStatus.FORBIDDEN); }

If we go to the Consul agent site, we'll see that our application is failing. To fix this, the “/my-health-check” service should return the HTTP 200 OK status code.

5. Distributed Configuration

This feature allows synchronizing the configuration among all the services. Consul will watch for any configuration changes and then trigger the update of all the services.

First, we need to add the spring-cloud-starter-consul-config dependency to our pom.xml:

 org.springframework.cloud spring-cloud-starter-consul-config 1.3.0.RELEASE 

We also need to move the settings of Consul and Spring application name from the application.yml file to the bootstrap.yml file which Spring loads first.

Then, we need to enable Spring Cloud Consul Config:

spring: application: name: myApp cloud: consul: host: localhost port: 8500 config: enabled: true

Spring Cloud Consul Config will look for the properties in Consul at “/config/myApp”. So if we have a property called “my.prop”, we would need to create this property in the Consul agent site.

We can create the property by going to the “KEY/VALUE” section, then entering “/config/myApp/my/prop” in the “Create Key” form and “Hello World” as value. Finally, click the “Create” button.

Bear in mind that if we are using Spring profiles, we need to append the profiles next to the Spring application name. For example, if we are using the dev profile, the final path in Consul will be “/config/myApp,dev”.

Now, let's see what our controller with the injected properties looks like:

@RestController public class DistributedPropertiesController { @Value("${my.prop}") String value; @Autowired private MyProperties properties; @GetMapping("/getConfigFromValue") public String getConfigFromValue() { return value; } @GetMapping("/getConfigFromProperty") public String getConfigFromProperty() { return properties.getProp(); } }

And the MyProperties class:

@RefreshScope @Configuration @ConfigurationProperties("my") public class MyProperties { private String prop; // standard getter, setter }

If we run the application, the field value and properties have the same “Hello World” value from Consul.

5.1. Updating the Configuration

What about updating the configuration without restarting the Spring Boot application?

If we go back to the Consul agent site and we update the property “/config/myApp/my/prop” with another value like “New Hello World”, then the field value will not change and the field properties will have been updated to “New Hello World” as expected.

En effet , le champ des propriétés est une MyProperties classe a la @RefreshScope annotation. Tous les beans annotés avec l' annotation @RefreshScope seront actualisés après les modifications de configuration.

Dans la vraie vie, nous ne devrions pas avoir les propriétés directement dans Consul, mais nous devrions les stocker de manière persistante quelque part. Nous pouvons le faire en utilisant un serveur de configuration.

6. Conclusion

Dans cet article, nous avons vu comment configurer nos applications Spring Boot pour qu'elles fonctionnent avec Consul à des fins de découverte de services, personnaliser les règles de vérification de l'état et partager une configuration distribuée.

Nous avons également introduit un certain nombre d'approches permettant aux clients d'invoquer ces services enregistrés.

Comme d'habitude, les sources peuvent être trouvées sur GitHub.