Introducción a la Gestión de Configuración Distribuida
En una arquitectura de microservicios, la gestión de la configuración se vuelve crítica. Mantener archivos de propiedades dispersos en cada servicio dificulta el mantenimiento y las actualizaciones. Spring Cloud Config proporciona una solución de servidor-cliente que permite externalizar y centralizar la configuración de todas las aplicaciones en un repositorio Git.
Las ventajas principales de este enfoque incluyen:
- Gestión centralizada de propiedades para diferentes entornos (desarrollo, pruebas, producción).
- Separación total entre el código de la aplicación y la configuración.
- Actualización dinámica de valores sin necesidad de rieniciar las instancias de los servicios.
Implementación del Servidor de Configuración (Config Server)
El primer paso es crear un servicio que actúe como el proveedor centralizado de configuraciones. Este servidor se conectará a un repositorio remoto para leer los archivos YAML o properties.
1. Preparación del Repositorio Git
Se debe crear un repositorio en una plataforma como GitHub o Gitee. Dentro del repositorio, creamos un archivo de configuración para uno de nuestros servicios, por ejemplo servicio-productos-dev.yml, con el siguiente contenido:
app:mensaje: Bienvenido al sistema de gestion dinamicaversion: 1.0.0
2. Configuración del Proyecto Maven
Crearemos un nuevo módulo llamado config-server (o servidor-configuracion). Debemos agregar la dependencia spring-cloud-config-server al archivo pom.xml.
<dependencies> <!-- Dependencia del Servidor Config --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency></dependencies>
3. Clase Principal y Activación
En la clase principal de la aplicación, es necesario añadir la anotación @EnableConfigServer para activar la funcionalidad del servidor.
package com.ejemplo.config;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication@EnableConfigServer // Habilita el servidor de configuraciónpublic class ServidorConfigAplicacion { public static void main(String[] args) { SpringApplication.run(ServidorConfigAplicacion.class, args); }}
4. Configuración del Servidor (application.yml)
Definimos el puerto y apuntamos al repositorio Git creado anteriormente. La configuración especifica la URL del repositorio y la rama por defecto.
server: port: 8888spring: application: name: servidor-configuracion cloud: config: server: git: uri: https://gitee.com/usuario/repositorio-configuracion.git default-label: master
Al iniciar el servidor, podemos acceder a la configuración mediante la URL: http://localhost:8888/master/servicio-productos-dev.yml.
Implementación del Cliente de Configuración (Config Client)
Ahora configuramos un microservicio cliente que leerá sus propiedades desde el servidor central en lugar de su propio sistema de archivos local.
1. Dependencias del Cliente
Agregamos spring-cloud-starter-config al proyecto cliente.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId></dependency>
2. Archivo bootstrap.yml
A diferencia de las configuraciones normales, la conexión al Config Server debe ocurrir antes de que la aplicación se enicialice completamente. Por ello, usamos bootstrap.yml en lugar de application.yml para definir la conexión.
spring: application: name: servicio-productos # Debe coincidir con el nombre del archivo en Git cloud: config: uri: http://localhost:8888 label: master profile: dev # Se concatenará: servicio-productos-dev.ymlserver: port: 8081
3. Lectura de Configuración
Podemos inyectar los valores definidos en el repositorio Git directamente en nuestros controladores o servicios.
package com.ejemplo.productos.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class InfoControlador { @Value("${app.mensaje}") private String mensajeSistema; @GetMapping("/info") public String obtenerInfo() { return "Mensaje leído desde Git: " + mensajeSistema; }}
Actualización Dinámica (Hot Refresh)
Por defecto, si modificamos el archivo en Git, el cliente no reflejará el cambio hasta que se reinicie. Para solucionar esto sin reiniciar, podemos implementar la funcionalidad de refresco.
1. Habilitar Actuator y Refresh Scope
Necesitamos la dependencia spring-boot-starter-actuator y exponer el endpoint refresh. Además, debemos anotar el bean que contiene la configuración con @RefreshScope.
@RestController@RefreshScope // Permite actualizar valores en tiempo de ejecuciónpublic class InfoControlador { // ... código anterior ...}
Configuración para exponer el endpoint:
management: endpoints: web: exposure: include: refresh
2. Disparar la Actualización
Cuando se actualiza el archivo en el repositorio Git, se debe enviar una petición POST al cliente para forzar la recarga de la configuración.
Comando: curl -X POST http://localhost:8081/actuator/refresh
Esto actualizará los valores inyectados en los beans anotados con @RefreshScope.
Alta Disponibilidad: Registrando Config Server en Eureka
Para evitar un punto único de fallo, el Servidor de Configuración puede registrarse como un servicio en Eureka. Los clientes entonces descubrirán el servidor automáticamente a través del registro del servicio.
Agregamos la dependencia de Eureka Client al Config Server y configuramos la ubicación del servidor de nombres:
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
En el lado del cliente (bootstrap.yml), en lugar de especificar la URI fija, habilitamos el descubrimiento:
spring: cloud: config: discovery: enabled: true service-id: servidor-configuracion