Écrit par Walid Najjar
Dans un environnement de microservices, chaque instance de service utilise plusieurs fichiers de configuration pour répondre à divers besoins et environnements. Cependant, la difficulté réside dans le fait que modifier un paramètre nécessite d’arrêter toutes les instances du microservice, de mettre à jour la configuration et enfin de redéployer.
Avant de procéder à cette manipulation, il faut avertir les utilisateurs via un message sur l’application, en indiquant la date et l’heure de son indisponibilité.
Pourquoi Spring Cloud Config ?
Spring Cloud Config est une solution puissante permettant de centraliser la configuration des microservices. Le stockage et la récupération des configurations est plus facile (voir quasi immédiat car un seul emplacement des paramètres) dans le but d’améliorer la scalabilité et la maintenance des systèmes distribués en minimisant l’impact client.
Architecture de Spring Cloud Config
L’architecture de Spring Cloud Config est simple mais robuste. Elle se compose d’un serveur de configuration, d’un dépôt de configuration et d’ applications clientes. Le serveur expose une API REST qui permet aux clients de récupérer les configurations en fonction de leur nom d’application et de leur profil.
Le dépôt de configuration est un dépôt central permettant le stockage des configurations des applications. Ce dépôt peut être basé sur un système de gestion de versions (Git, SVN, etc.) et contient des fichiers de configuration au format YAML, JSON ou properties.
Les clients interagissent avec le serveur de configuration pour récupérer leurs paramètres selon leur environnement (développement, test, production, etc.). Ces clients peuvent être des applications Spring ou non-Spring.
Architecture Spring Cloud Config
Intégration avec Spring Boot
Spring Cloud Config s’intègre parfaitement avec Spring Boot.
En utilisant l’annotation @EnableConfigServer
sur un service Spring Boot, celui-ci peut être configuré en tant que serveur de configuration. Les applications clientes Spring Boot peuvent également utiliser l’annotation @RefreshScope
pour dynamiquement rafraîchir leur configuration sans redémarrer.
Exemple :
Partie 1
Pour exploiter Spring Cloud Config dans une application Spring Boot, il est impératif d’inclure la dépendance spring-cloud-config-server
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ma.config</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>config-server</name>
<description>Serveur Spring Cloud Config</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
<spring-cloud.version>2020.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Ajoutez les lignes ci-dessous au fichier application.properties et renseignez l’URL de dépôt de configuration distant :
spring.cloud.compatibility-verifier.enabled=false
spring.application.name=config-server
server.port:8082
spring.cloud.config.server.git.uri=https://github.com/my-repo/config-server-repo.git
Il suffit maintenant de déclarer ce microservice comme étant un serveur de configuration, grâce à @EnableConfigServer
.
package com.mon.package.configserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
On obtient alors par exemple :
{
"name": "mon-microservice",
"profiles": [
"default"
],
"propertySources": [
{
"name": "https://github.com/aiwanesk/config-server-repo.git/mon-microservice.properties",
"source": {
"app.conf.valeur": "4",
"server.port": "8081",
"spring.datasource.sql-script-encoding": "UTF-8",
"spring.h2.console.enabled": "true",
"spring.jpa.show-sql": "true"
}
}
],
"label": null,
"state": null,
"version": "6c110ea5696e6d23a71fac53228643c40ac12acff"
}
Le serveur va récupérer le fichier de configuration depuis le référentiel GIT et expose désormais une API accessible via l’URL “/nom-du-microservice/default”.
En réponse, il fournit toutes les configurations présentes dans le fichier au format JSON.
Partie 2
Nous disposons d’un dépôt distant connecté à notre serveur Spring Cloud Config.
Il suffit maintenant de demander au service « Mon-Microservice » de récupérer la configuration à partir du serveur de configuration.
Pour accomplir cela, il est nécessaire de mettre à jour le fichier pom.xml de « Mon-Microservice » en y ajoutant le starter spring-cloud-starter-config :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mon.application</groupId>
<artifactId>mon-microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mon-microservice</name>
<description>Mon Microservice</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
<spring-cloud.version>2020.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Ensuite, il est nécessaire de modifier le nom du fichier application.properties en bootstrap.properties puis ajoutez :
spring.cloud.config.uri=http://localhost:8081
Lorsqu’une valeur est modifiée dans le référentiel de configuration, notre microservice doit prendre en compte cette nouvelle valeur.
Pour réaliser cela, il est nécessaire de déclencher un signal “Refresh” en lui envoyant une requête.
Pour ce faire, On doit intégrer Spring Actuator à notre microservice, ce qui exposera l’URI /refresh pour forcer la mise à jour des valeurs de configuration.
Ainsi, il est nécessaire de modifier le fichier pom.xml de notre microservice afin d’y intégrer Spring Actuator.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Ensuite, il est nécessaire de mettre à jour le fichier “bootstrap.properties” afin d’activer l’endpoint refresh d’Actuator :
management.endpoints.web.exposure.include=refresh
Nous allons désormais spécifier à notre beans de configuration du service « Mon-Microservice » de se mettre à jour la configuration chaque fois qu’un événement « Refresh » est déclenché. Pour ce faire, nous allons ajouter l’annotation @RefreshScope
à notre classe de configuration :
@Data
@Component
@ConfigurationProperties("app.conf")
@RefreshScope
public class ApplicationPropertiesConfiguration
{
private int valeur;
}
Sécurité et Gestion des Versions
Des mécanismes de sécurité robustes protègent l’accès aux configurations sensibles par le bias de systèmes d’authentification tels que OAuth2 ou l’authentification de base.
De plus, le support de gestion des versions via des branches Git permet de gérer différentes versions de configuration pour différentes phases de développement.
Conclusion
En conclusion, Spring Cloud Config offre une solution robuste pour la gestion centralisée de la configuration dans les environnements de microservices.
Cette technologie présente les avantages suivants :
- Centralisation : La centralisation de la configuration simplifie la gestion des paramètres dans un environnement distribué;
- Gestion dynamique : Les mises à jour de configuration peuvent être appliquées dynamiquement sans redémarrage des services;
- Sécurité : Les mécanismes de sécurité intégrés assurent la protection des données de configuration sensibles;
- Gestion des versions : La gestion des versions via Git permet de suivre les changements et de revenir à des versions antérieures si nécessaire.
Avec son intégration transparente avec Spring Boot, Spring Cloud Config devient un outil incontournable pour les équipes de développement travaillant sur des architectures de microservices.