Config client
El cliente que vamos a construir será bastante simple, pero demostrará lo principal de la extenalización.Lo que hará nuestro cliente será:
- Disponer de un fichero de configuración mínimo dentro de la propia aplicación (bootstrap.yml)
- Al arrancar conectará contra el server-config, que escucha en el puerto 8888.
- El server-config resolverá en gitlab (o en su caché local) a través del nombre de la aplicación cliente, y del profile activo, la configuración a entregar el cliente.
- El cliente acabará de levantarse a partir de los datos recibidos.
Para que sea más patente el atractivo de este starter, haremos que el puerto de arranque de la aplicación cliente sea recibido desde el server-config. Veremos que algo que parece tan básico como el puerto de arranque puede externalizarse como cualquier otro atributo.
También veremos un servicio rest que recupera el valor de una variable, que una vez todo arrancado y servida en una petición de prueba, podrá ser modificada, y actualizada "en caliente".
El código completo (server, cliente y ficheros de configuración) se pueden descargar de nuestro repositorio gitlab. Los enlaces los podéis encontrar al final de esta entrada.
Comencemos.
pom.xml
Hemos de añadir en nuestro cliente la siguiente dependencia específica
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
Además añadimos estas otras
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config</artifactId>
<version>2.0.0.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
bootstrap.yml
Como decíamos al principio, debemos incluir una mínima configuración en nuestro cliente. Es la siguiente:
spring:
application:
name: config-client-example
profiles:
active: des
cloud:
config:
uri: http://localhost:8888
Esta es la mínima información, necesaria para que nuestro cliente conecte contra el server-config (http://localhost:8888), y mediante el name (config-client-example) y el profile (des) genera la url de recuperación de la configuración: http://localhost/8888/config-client-example/des. Si ponemos esta url en nuestro navegador veremos que el server-config (que está a la escucha en el puerto 8888) hará de puente y recuperará la configuración del gitlab, vendiéndosela al cliente para que continúe el arranque.
En logs de arranque de nuestro cliente deberemos ver algo parecido a:
....Fetching config from server at: http://localhost:8888
....Located environment: name=config-client-example, profiles=[des], label=null, version=5a96400b412b4dfd5bb4a34a8fcabe0a0387077a, state=null
....Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://gitlab.com/gincol-blog/config-files.git/config-client-example/application-des.yml'}]}
Estas trazas nos indican que el cliente, en momento de arranque, ha conectado con el server-config, y pedido su configuración según la ruta detallada más arriba.
spring:
application:
name: config-client-example
profiles:
active: des
cloud:
config:
uri: http://localhost:8888
Esta es la mínima información, necesaria para que nuestro cliente conecte contra el server-config (http://localhost:8888), y mediante el name (config-client-example) y el profile (des) genera la url de recuperación de la configuración: http://localhost/8888/config-client-example/des. Si ponemos esta url en nuestro navegador veremos que el server-config (que está a la escucha en el puerto 8888) hará de puente y recuperará la configuración del gitlab, vendiéndosela al cliente para que continúe el arranque.
En logs de arranque de nuestro cliente deberemos ver algo parecido a:
....Fetching config from server at: http://localhost:8888
....Located environment: name=config-client-example, profiles=[des], label=null, version=5a96400b412b4dfd5bb4a34a8fcabe0a0387077a, state=null
....Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://gitlab.com/gincol-blog/config-files.git/config-client-example/application-des.yml'}]}
Estas trazas nos indican que el cliente, en momento de arranque, ha conectado con el server-config, y pedido su configuración según la ruta detallada más arriba.
application-des.yml
Este fichero reside en el gitlab, y es responsabilidad del server-config el servirlo al cliente en momento de arranque de dicho cliente.
Su contenido será el siguiente:
server:
port: 8181
management:
endpoints:
web:
exposure:
include: refresh, info, health, metrics, trace
user:
role: Desarrollador
Su contenido será el siguiente:
server:
port: 8181
management:
endpoints:
web:
exposure:
include: refresh, info, health, metrics, trace
user:
role: Desarrollador
Indicamos el puerto de arranque, que será el 8181. Indicamos también los endopoints activos (ver nuestra entrada sobre el starte actuator).
Indicamos asimismo un parámetro propio "user.role" de forma que veamos como opera este tipo de configuración en nuestro app.
Indicamos asimismo un parámetro propio "user.role" de forma que veamos como opera este tipo de configuración en nuestro app.
java
En el Application.java ponemos la anotación ya conocida "@SpringBootApplication".
Crearemos un @RestController, que recuperará el valor de una variable del fichero de configuración servido por el server. El controller tiene este aspecto:
@RestController
@RefreshScope
public class MainController {
@Value("${user.role}")
String role = "User";
@GetMapping(path = "/whoami/{username}")
public String whoami(@PathVariable("username") String username) {
return String.format("Hola! %s, eres %s", username, role);
}
}
La anotación "@RefreshScope" es la que nos permitirá cambiar valores de configuración, recuperados en esta clase (se ha de poner esta anotación en cualquier clase que recupere variables del server).
La anotación "@Value" hará el binding con la variable "user.role" extraída del fichero de configuración externalizado en momento de arranque.
Prueba
Si arrancamos ahora nuestro cliente veremos el siguiente resultado (http://localhost:8181/whoami/ginés):
Vemos que el puerto, efectivamente es el 8181, que, recordemos, está ubicado en el fichero application-des.yml que hay en el gitlab, y que es servido a través del server-config.
Modifiquemos ahora el valor de la variable "user.role: Desarrollador" y pongamos "user.role: Arquitecto".
Si invocamos de nuevo la url anterior, veremos que nada cambia, nuestro cliente no es capaz de recuperar el nuevo valor.
Para que el cambio tenga efecto, hemos de invocar la url del endopoint "/refresh" del actuator. Importante, se ha de hacer via POST (en otro caso no funcionará). En nuestro caso, por simplicidad, lo hacemos lanzando el comando curl (si no tenéis una consola cygwin o git bash en vuestro windows, podéis usar cualquier cliente rest, Insomnia por ejemplo, para realizar la invocación POST)
Fijaos que invocamos el actuator a nivel de nuestra aplicación cliente, no del server-config. La salida esperada será semejante a la siguiente:
Si ahora invocamos de nuevo nuestro servicio rest (http://localhost:8181/whoami/ginés) veremos, ahora sí, el cambio:
Sin re-despliegue de ningún artefacto, sin reinicio de ninguna aplicación. ¿Magia? Es lo que parece, pero no, es la maravillosa conjunción de externalización y actuator, dos starter Spring muy sencillos pero que proveen de funcionalidades realmente atractivas, especialmente en entornos cloud.
server-config: https://gitlab.com/gincol-blog/config-server-example.git
client-config: https://gitlab.com/gincol-blog/config-client-example.git
ficheros-config: https://gitlab.com/gincol-blog/config-files.git
Esta es la configuración completa de los tres proyectos vista desde eclipse:
Modifiquemos ahora el valor de la variable "user.role: Desarrollador" y pongamos "user.role: Arquitecto".
Si invocamos de nuevo la url anterior, veremos que nada cambia, nuestro cliente no es capaz de recuperar el nuevo valor.
Para que el cambio tenga efecto, hemos de invocar la url del endopoint "/refresh" del actuator. Importante, se ha de hacer via POST (en otro caso no funcionará). En nuestro caso, por simplicidad, lo hacemos lanzando el comando curl (si no tenéis una consola cygwin o git bash en vuestro windows, podéis usar cualquier cliente rest, Insomnia por ejemplo, para realizar la invocación POST)
curl -X POST http://localhost:8181/actuator/refresh
Fijaos que invocamos el actuator a nivel de nuestra aplicación cliente, no del server-config. La salida esperada será semejante a la siguiente:
Si ahora invocamos de nuevo nuestro servicio rest (http://localhost:8181/whoami/ginés) veremos, ahora sí, el cambio:
Sin re-despliegue de ningún artefacto, sin reinicio de ninguna aplicación. ¿Magia? Es lo que parece, pero no, es la maravillosa conjunción de externalización y actuator, dos starter Spring muy sencillos pero que proveen de funcionalidades realmente atractivas, especialmente en entornos cloud.
Más info
El código completo lo tenéis enserver-config: https://gitlab.com/gincol-blog/config-server-example.git
client-config: https://gitlab.com/gincol-blog/config-client-example.git
ficheros-config: https://gitlab.com/gincol-blog/config-files.git
Esta es la configuración completa de los tres proyectos vista desde eclipse:
Se puede consultar la página oficial de Spring para este starter en https://spring.io/guides/gs/centralized-configuration/




No hay comentarios:
Publicar un comentario