Patrón: Configuración Centralizada (I)
La dispersión de los microservicios en la infraestructura implica que realizar cambios de configuración sea un proceso costoso en cuanto a tiempo y esfuerzo. El patrón de configuración centralizada propone que todas las configuraciones de los sistemas sean ubicadas en un único lugar, los sistemas serán capaces en el proceso de arranque buscar sus configuraciones en el servicio remoto y trabajar con ellas. El uso de configuraciones centralizadas tiene el reto de ante un cambio en la configuración de un sistema que está en producción, como inyectar esa configuración para que el sistema pueda seguir operando con los nuevos parámetros, sin necesidad de reiniciar el servicio para que recargue la configuración.
En los esquemas de configuración centralizada hay varias formas de servir la configuración:
- Llave – valor: En este tipo de esquema el sistema que requiere la configuración pregunta por una llave al proveedor de configuraciones y se le entrega el valor de la llave, un ejemplo tecnología que implementa este esquema es HashiCorp Vault.
- Ficheros: El cliente solicita basado en un nombre o id un fichero de configuración que el proveedor de configuraciones entrega.
El segundo esquema de ficheros es el empleado por Spring Cloud Config / Netflix Archaius, es extremadamente flexible y útil pues el servidor de configuraciones tiene la posibilidad de obtener los ficheros desde un SCM como GIT sirviendo siempre la última configuración de una rama especificada.
GIT por su parte se encarga de la gestión del versionado de los ficheros lo que nos permite a la vez que llevar el control histórico de los cambios, poder hacer rollback de una forma sencilla a una configuración conocida que funcione ante errores.
En el caso particular de Spring Cloud Config el problema planteado de inyectar las configuraciones en caliente se resuelve combinando Spring Cloud Bus y un sistema de cola de mensajes MQ como Rabbit o Active, pasando una notificación a los clientes para que hagan auto-refrescamiento de las properties ante un nuevo cambio.
Cuando usar configuración centralizada
Si el entorno de microservicios tiende a ser grande (+ de 5 entidades) y las configuraciones pueden tener variabilidad ó se manejan datos sensibles en la configuración que deberían estar protegidos.
Herramientas recomendadas
Entre las herramientas recomendadas para implementar el patrón de configuración centralizada están:
- Spring Cloud Config / Netflix Archaius
- HashiCorp Vault
- HashiCorp Consul
- Zookeeper
Spring Cloud
Spring Cloud dispone de herramientas para construir un completo entorno cloud, con implementación de la mayoría de los patrones que guían una arquitectura de microservicios.
Ejemplo de configuración centralizada con Spring Cloud Config
Para desplegar configuración centralizada en Spring Cloud se requiere montar un servidor que sirva la configuración a los clientes y las aplicaciones que la consumen.
Spring Cloud Config Server
Pivotal provee un starter de Spring Boot que ya nos provee todo lo necesario para poner un servidor de configuraciones en funcionamiento, solo necesitamos agregar la dependencia:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
Nota: No especificamos la versión pues por defecto Spring Boot incluye la acorde a la versión de Spring Cloud que estamos usando, en este caso Hoxton.SR1
Luego de incluida la dependencia la creación del servidor se resume a anotar el main principal de Spring Boot con @EnableConfigServer.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
Por configuración se define donde estarán las configuraciones y la forma en que se gestionarán, para este ejemplo usaremos Git para versionar y almacenar la configuración. El siguiente fichero de configuración corresponde al servidor de configuraciones.
server.port=8888 spring.application.name=config-server spring.cloud.config.enabled=true spring.cloud.config.server.git.uri=file:///opt/microservices/config-repository
Esta configuración establece que el servidor de configuraciones se iniciará en el puerto 8888, habilitado y que la configuración se leerá de un Git cuyo espacio de trabajo está en el directorio local /opt/microservices/config-repository.
La configuración debe almacenarse en un Git, para este ejemplo está disponible acá.
La configuración en el Git debe guardarse siguiendo una convención de nombres para que sea consultada.
<nombre-app>-<profile>.yml ó <nombre-app>-<profile>.properties
Ejemplo: books-dev.yml, será la configuración de un microservicio cuyo spring.application.name=books para el perfil dev. Osea cuando la aplicación books levante con perfil dev buscará este fichero de configuración en el servidor de configuraciones.
Una vez iniciado el servidor de configuraciones, por método HTTP GET se puede consultar la configuración, para el ejemplo en cuestión:
- HTTP GET http://localhost:8888/books/master (Nos dará la configuración de la aplicación books cuando no se ha establecido un perfil).
- HTTP GET http://localhost:8888/books/dev (Nos dará la configuración de la aplicación books cuando no se ha establecido el perfil dev).
Aunque no se ha establecido seguridad es posible hacerlo.
Microservicio: books, ejemplo de cliente.
Como ejemplo de cliente vamos a crear una app básica que lea la configuración del servidor y la muestre. En sucesivos artículos agregaremos mas complejidad, es un ejemplo solo básico e ilustrativo.
Más allá de que la configuración se ofrece en el servidor de configuraciones por HTTP GET. Existe un starter de Spring Cloud para los clientes, lo podemos usar agregando la dependencia:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
Una vez agregada esta dependencia, en la aplicación cliente debemos indicarle donde leer la configuración desde el fichero de configuraciones, para este caso:
spring.application.name=books spring.cloud.config.uri=http://localhost:8888 spring.profiles.active=dev
Como se puede ver en la configuración destaca el application.name = books, este nombre debe coincidir con un fichero de properties en el servidor, de lo contrario no se encontrará una configuración y fallará el arranque, a menos que exista una configuración por defecto.
Una vez se haya añadido, cuando arranque el proyecto, antes de crearse los beans de spring se inyectarán las configuraciones que coincidan y estén disponibles.
En el proyecto ms-books hemos creado un Controller en el que leemos una property de la configuración almacenada en el servidor de configuraciones, en este caso “books.welcome.message“, el siguiente código corresponde al controlador.
@RestController @RequestMapping("/api/v1") public class BookController { @Value("${books.welcome.message}") private String welcomeMessage; private static final Logger logger = LoggerFactory.getLogger(BookController.class); @GetMapping("/books") public ResponseEntity<String > postBook() { logger.info("Request done"); return new ResponseEntity<>(welcomeMessage, HttpStatus.OK); } }
Actualización automática
La configuración centralizada permite tener un solo lugar todos los archivos de configuración, permitiendo su versionado, seguridad y mayor control. Sin embargo el gran reto es la actualización automática de las properties cuando se produce un cambio en el servidor. En un próximo artículo abordaremos este tema y con Spring Cloud Bus veremos como actualizar automáticamente las properties.
Puedes acceder a los archivos de código fuente de esta aplicación en:
[1] – Microservicio de configuraciones.
[2] – Microservicio de ejemplo books.
[3] – Configuración centralizada de ejemplo.
Great content! Super high-quality! Keep it up! 🙂