Published by

Il y a 4 ans -

Temps de lecture 9 minutes

Patterns de microservices avec Spring Cloud (1/2)

Introduction

Il y a une dizaine d’années, la plupart des applications Web étaient construites selon un style architectural monolithique. Mais la plupart du temps, plusieurs équipes de développement travaillent sur l’application. Chaque équipe de développement a ses propres composants de l’application dont elle est responsable. Avec le temps, l’application grossit et il faut découper le monolithe pour pouvoir développer l’application en parallèle et pouvoir la déployer indépendamment. Le concept de microservices est une réponse directe au défi de la mise à l’échelle d’applications monolithiques.

Parallèlement, Spring, avec en particulier Spring Boot, est devenu le choix par défaut pour la création d’applications développées en Java. Les microservices étant devenus l’un des modèles d’architecture les plus courants pour la création d’applications basées sur le cloud, la communauté de développement Spring nous a fourni Spring Cloud parce que Spring Boot n’implémente pas les patterns spécifiques aux architectures microservice qui vont être présentés. Dans cette série d’articles, nous passerons en revue plusieurs des patterns proposés par Spring Cloud :

  • Gestion de la configuration
  • Découverte de services
  • Passerelle de service
  • Circuit breaker, Fallback processing, Bulkhead

Un premier article présentera la gestion de la configuration, avec Spring Config, et la découverte de services, avec Eureka. Il sera suivi d’un second article, qui abordera les passerelles de services avec Zuul et les notions de circuit breakers, de fallback processing et de bulkhead avec Hystrix.

Gestion de configuration – Spring Cloud Config

Introduction du problème

Les données de configuration d’application écrites directement dans le code sont souvent problématiques, car chaque fois qu’une modification de la configuration doit être effectuée, l’application doit être recompilée et / ou redéployée. Pour éviter cela, il est recommandé aux développeurs de séparer complètement les informations de configuration du code de l’application (le troisième facteur de la méthodologie Twelve-Factor App).

Il est possible d’utiliser un fichier de propriétés (YAML, JSON, XML, etc.) pour stocker leurs informations de configuration.

Cette approche peut s’appliquer à un petit nombre d’applications, mais elle devient rapidement trop lourde lorsqu’il s’agit d’applications distribuées pouvant contenir des centaines de microservices.

Pour résoudre ce problème, nous allons utiliser Spring Cloud Config qui implémente le pattern Gestion de configuration.

Diagramme du pattern

Le diagramme ci-dessous présente la récupération de la configuration par les instances de microservices lors de leur démarrage.

Description du pattern

Spring Cloud Config gère les données de configuration des applications via un service centralisé, de sorte que les données de configuration de vos applications (en particulier celles de votre environnement) soient clairement séparées de votre microservice déployé. Cela garantit que, peu importe le nombre d’instances de microservices que vous avez lancées, elles auront toujours la même configuration. Spring Cloud Config possède son propre dépôt de gestion de propriétés, mais s’intègre également à des projets open source tels que Git, Consul et Eureka. Nous allons utiliser Git dans cet article.

Le développement de microservices dans le cloud nécessite :
  • la séparation de la configuration d’une application du code
  • la construction du serveur et de l’application : les livrables ne seront plus recompilés, mais promus d’un environnement à un autre
  • l’injection d’informations de configuration d’application au démarrage du serveur par le biais de variables d’environnement ou d’un dépôt centralisé

Configuration de Spring Cloud Config

pom.xml
<!-- Les dépendances de Spring Cloud Config -->
 
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
  </dependency>
application.yml

[xml]# Spring Cloud Config application.yml

server:
port: 8888 # le port de Spring Cloud Config
spring:
cloud:
config:
server:
git:
uri: file:///Users/oslynko/IdeaProjects/springmicroservices/config-repo/ # uri du dépôt Git qui contient la configuration[/xml]

ConfigServerApplication.java

[java]@SpringBootApplication
@EnableConfigServer // l’annotation qui permet la gestion de la configuration
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
[/java]

Exemple de Postman

Nous allons utiliser les profils Spring pour les tests Postman. Il y a 2 fichiers dans le dépot:

  • message-service.yml
  • message-service-dev.yml

La convention de nommage des fichiers est {application}-{profile}.yml

Nous allons utiliser Postman pour récupérer les propriétés de configuration avec le profil par défaut, puis avec le profil dev.

En cas d’appel à http://localhost:8888/message-service/default, Spring Cloud Config prend les propriétés du fichier message-service.yml qui se trouve dans le dépôt

En cas d’appel à http://localhost:8888/message-service/dev, Spring Cloud Config prend les propriétés du fichier message-service-dev.yml qui se trouve dans le dépôt

Exemple d’interaction

Pour tester l’intégration, nous allons créer un microservice d’exemple (le service « Message ») qui va récupérer ses propriétés depuis Config Server.

application.yml

[xml]# Message service application.yml

server:
port: 8080 # le port du microservice d’exemple (Message service)
spring:
application:
name: message-service # le nom du service, le nom est utilisé pour identification
cloud:
config:
uri: http://localhost:8888 # Spring Cloud Config uri, toutes les propriétés viennent de ce service[/xml]

bootstrap.properties

[xml]# Message service bootstrap.properties

spring.profiles.active=dev[/xml]

MessageController.java

[java]@RestController
public class MessageController {

@Value("${message}") // la valeur ‘message’ vient de Spring Cloud Config service
private String message;

@GetMapping("/message")
public String getMessage() {
return message;
}
} [/java]

En cas d’appel à http://localhost:8080/message, Message service prend les propriétés de Spring Cloud Config qui prend les propriétés du fichier message-service-dev.yml

Conclusion

  • Spring Cloud Config vous permet de configurer les propriétés de l’application avec des valeurs spécifiques à l’environnement
  • Spring utilise des
    profils Spring pour lancer un service afin de déterminer les propriétés d’environnement à extraire du service Spring Cloud Config
  • Spring Cloud Config peut utiliser un dépôt de configuration d’application basé sur un fichier ou sur Git pour stocker les propriétés de l’application

Découverte de services – Spring Cloud / Netflix Eureka

Introduction du problème

Si une équipe gère des serveurs physiques, un fichier de configuration répond essentiellement au besoin de découverte de services, ce fichier permet de savoir quelle adresse utiliser pour appeler un service.

Mais vos services peuvent avoir un emplacement réseau dynamique en raison d’un redémarrage, d’une défaillance et d’une mise à l’échelle. Maintenir manuellement un fichier de configuration n’est tout simplement pas faisable.

Pour résoudre ce problème, nous allons utiliser Eureka qui implémente le pattern Découverte de services.

Diagramme du pattern

Description du pattern

  • La découverte de services est essentielle pour les microservices pour deux raisons principales. Elle offre à l’application la possibilité d’augmenter rapidement le nombre d’instances de service exécutés
    dans un environnement. Les consommateurs de services sont abstraits de l’emplacement physique du service via la découverte de services. Étant donné que les consommateurs de services ne connaissent pas l’emplacement physique des instances de service réelles, de nouvelles instances de service peuvent être ajoutées ou supprimées du pool de services disponibles.
  • Cette capacité à adapter rapidement les services sans perturber les utilisateurs de services permet à une équipe de développement habituée à la création d’applications monolithiques d’adopter l’approche la plus puissante pour la mise à l’échelle en ajoutant davantage de serveurs.

  • Le deuxième avantage de la découverte de services est qu’elle contribue à augmenter la résilience des applications. Lorsqu’une instance de microservice devient instable ou indisponible, la plupart des moteurs de découverte de services la suppriment de la liste interne des services disponibles. Les dommages causés par un service indisponible seront minimisés car le moteur de découverte de services acheminera les appels aux services disponibles.

Configuration de Eureka

pom.xml
<!-- Les dépendances de Eureka client (message service) -->
 
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
application.yml

[xml]# Eureka application.yml

server:
port: 8761
eureka:
client:
registerWithEureka: false # Ne pas s’enregistrer auprès du service Eureka.
fetchRegistry: false # Ne cache pas les informations de registre localement.
server:
waitTimeInMsWhenSyncEmpty: 5 # Temps initial d’attente avant que le serveur accepte les demandes[/xml]

EurekaApplication.java

[java]@SpringBootApplication
@EnableEurekaServer // l’annotation qui permet la découverte de services
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}[/java]

Configuration de Eureka client

pom.xml
<!-- Les dépendances de Eureka client (message service) -->
 
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
application.yml

[xml]# Eureka client (message service) application.yml

server:
port: 8080
spring:
application:
name: message-service # le nom du service, le nom est utilisé pour identification du service
eureka:
instance:
preferIpAddress: true
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/ # url de Eureka Server[/xml]

Exemple d’interaction

Nous avons configuré le serveur Eureka et le service Message. Nous allons maintenant les démarrer. Dans les logs du service Message, nous voyons les détails de l’enregistrement du service.

Dans les logs on peut voir que Message service enregistre l’adresse IP sur le serveur Eureka lors du démarrage.

En cas d’appel à http://localhost:8761, on voit que Message service a été enregistré auprès d’Eureka.

Pour tester l’intégration avec Eureka, nous utiliserons OpenFeign Declarative REST Client : OpenFeign crée une implémentation dynamique d’une interface décorée avec des annotations JAX-RS ou Spring MVC.

MessageServiceClient.java

[java]@FeignClient("message-service") // le nom du service
public interface MessageServiceClient {

@RequestMapping("/message") // openfeign va implémenter cette interface pour appeler le point de terminaison /message
String getMessage();

}[/java]

Sur la capture d’écran, nous voyons qu’OpenFeign a récupéré l’IP de Message service et a appelé le point de terminaison /message.
Conclusion
  • Eureka est utilisé pour abstraire la localisation physique des services.
  • Un moteur de découverte de services tel qu’Eureka peut ajouter et supprimer de manière transparente des instances de service d’un environnement sans que les clients du service ne soient affectés.
  • Eureka est un projet Netflix qui, lorsqu’il est utilisé avec Spring Cloud, est facile à configurer.

 

Pour aller plus loin, le code source du projet utilisé comme exemple est disponible sur Github : https://github.com/slynko/springmicroservices

Published by

Commentaire

3 réponses pour " Patterns de microservices avec Spring Cloud (1/2) "

  1. Published by , Il y a 4 ans

    Super intéressant et enrichissant pour les débutants en Spring, à quand le volet ?

  2. Published by , Il y a 4 ans

    Merci, la partie 2 est déjà en cours.

  3. Published by , Il y a 3 ans

    Salut,
    Sympa !

    néanmoins, sur la première partie (config via un repo git), je pense que l’on pourrait s’attendre à un autre fonctionnement :
    – tu tapes sur http://localhost:8888/message-service/ (pas de /default ni /dev) et ce endpoint retourne un message différent selon le profil avec lequel l’appli a été lancée (donc bootstrap.yml à retirer, et passer le profil en param d’appli/env)
    – montrer comment on stocke la configuration sur le repo git. Par quels fichiers se traduisent les profils ? Est-ce qu’on dépose juste des yml ? Avec quels noms ?

    Merci,

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.