Has aprendido cómo configurar Spring Cloud Config Server, conectarlo a un repositorio de configuraciones (por ejemplo, Git), y también cómo los microservicios clientes pueden obtener sus ajustes desde ese almacén centralizado. Todo esto está muy bien, pero aún queda la pregunta: ¿cómo actualizar la configuración sin reiniciar el microservicio? ¡Vamos, es hora de atacar esta fortaleza "al vuelo"! Hoy veremos cómo actualizar configuraciones dinámicamente usando Spring Cloud Bus y eventos. Sí, sí, todo ocurrirá en tiempo real.
Problemas con la actualización de configuraciones
Imagínate que eres el administrador de una aplicación que corre en una arquitectura distribuida de microservicios. Quieres cambiar una pequeña configuración, por ejemplo, la URL de una API externa o el nivel de logging. Sin actualización dinámica tendrías que:
- Primero cambiar los ajustes en la configuración.
- Luego reiniciar todos los microservicios afectados.
Suena a tarea que queremos evitar (manos arriba quienes aman el downtime!). Especialmente en producción, donde esos reinicios pueden fastidiar al usuario y a tus compañeros.
¿La solución? Actualización dinámica de configuraciones. En lugar de reiniciar el servicio, podemos actualizar las configuraciones "sobre la marcha" usando herramientas de la ecosistema Spring.
Enfoque para la actualización dinámica de configuraciones
¿Para qué sirve Spring Cloud Bus?
Spring Cloud Bus es una herramienta que conecta microservicios usando un sistema distribuido de mensajería. Para decirlo simple: permite "contarle" a otros servicios que ha habido cambios. Por ejemplo, al actualizar la configuración, Spring Cloud Bus puede notificar a todos los microservicios conectados para que recuperen las nuevas settings desde Spring Cloud Config Server.
¿Cómo funciona el proceso?
- Actualizas un archivo de configuración en Git (u otro almacén).
- El Config Server detecta y carga los cambios.
- Spring Cloud Bus, a través de un message broker (por ejemplo, RabbitMQ), notifica a todos los microservicios sobre el cambio.
- Los microservicios "cargan" las settings actualizadas localmente.
Práctica: actualización de configuraciones sobre la marcha
Qué vamos a usar:
- Spring Boot para los microservicios.
- Spring Cloud Config para el manejo centralizado de configuraciones.
- Spring Cloud Bus para las notificaciones.
- RabbitMQ como message broker.
Puedes usar otro broker, por ejemplo Apache Kafka, pero para nuestro ejemplo elegimos RabbitMQ porque es fácil de poner en marcha y compatible con Spring Cloud Bus.
Pasos de implementación
Paso 1: Configurar RabbitMQ
Lo primero es instalar RabbitMQ. Si ya lo tienes instalado y funcionando, puedes pasar al siguiente paso.
Para instalarlo con Docker usa:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management
- La interfaz de administración de RabbitMQ está disponible en:
http://localhost:15672/ - Login:
guest, contraseña:guest.
Paso 2: Configurar Spring Cloud Config Server
Usaremos el Config Server que ya creamos en las lecciones anteriores. Añade la siguiente dependencia en el pom.xml de tu Config Server:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Esta dependencia conecta Spring Cloud Bus usando RabbitMQ.
Ahora añade en el archivo application.yml del Config Server las siguientes settings:
spring:
cloud:
bus:
enabled: true
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
Con esto, el Config Server quedará conectado a RabbitMQ para publicar eventos en el bus.
Paso 3: Configurar el microservicio cliente
En el microservicio cliente añade también la dependencia spring-cloud-starter-bus-amqp en el pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Y configura la conexión a RabbitMQ añadiendo en el application.yml del cliente:
spring:
cloud:
config:
uri: http://localhost:8888 # URL Config Server
bus:
enabled: true
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
management:
endpoints:
web:
exposure:
include: refresh, bus-refresh
Fíjate en management.endpoints.web.exposure.include. Esta línea nos permite invocar los endpoints /actuator/refresh y /actuator/bus-refresh.
Paso 4: Usar la anotación @RefreshScope
Ahora vamos a cambiar el comportamiento de nuestro servicio para que actualice dinámicamente las settings. Para eso usamos la anotación @RefreshScope.
Ejemplo de código:
@RestController
@RequestMapping("/api")
public class MyController {
@Value("${custom.message:Default message}") // Enlazamos con la configuración
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
Añade la anotación @RefreshScope a nivel de clase:
@RefreshScope
@RestController
@RequestMapping("/api")
public class MyController {
// el resto del código sin cambios
}
Ahora, cada vez que se actualice la configuración, el campo message se recargará automáticamente.
Paso 5: Actualizar la configuración
Cuando hagas cambios en la configuración (por ejemplo, un archivo en Git), llama a esta API en el servidor:
curl -X POST http://localhost:8080/actuator/bus-refresh
Donde 8080 es el puerto del Config Server.
Esta acción enviará una notificación a todos los clientes suscritos a través de Spring Cloud Bus para que actualicen sus configuraciones.
Pruebas
Vamos a probar todo:
- Asegúrate de que todos los servicios estén en marcha (RabbitMQ, Config Server, microservicio cliente).
- Cambia el archivo de configuración en el repositorio (por ejemplo, en Git) — modifica el valor de la propiedad
custom.message. - Ejecuta el comando
curl -X POST http://localhost:8080/actuator/bus-refreshpara propagar la actualización. - Solicita
http://localhost:8081/api/message(donde8081es el puerto del cliente) antes y después de la actualización. Deberías ver el nuevo valor de la propiedad.
Notas generales
- Si te olvidas de añadir la anotación
@RefreshScope, los cambios no se aplicarán "sobre la marcha". Es uno de los errores más comunes. - Spring Cloud Bus soporta varios brokers de mensajes. RabbitMQ es bueno para empezar rápido, pero en sistemas más complejos puedes usar Kafka para mayor fiabilidad.
- Asegúrate de haber incluido
bus-refreshenmanagement.endpoints.web.exposure.include, si no el API de actualización no estará disponible.
Ahora tu aplicación puede actualizar configuraciones dinámicamente y ya no hace falta reiniciar los microservicios.
GO TO FULL VERSION