Trazabilidad en microservicios con Spring Cloud Sleuth
Escrito por
el , actualizado el .
java
planeta-codigo
Enlace permanente
Comentarios
Los microservicios son independientes pero se llaman unos a otros, suele ser muy útil para tareas de depuración y de visibilidad de una petición disponer de la traza completa de una petición a lo largo de las llamadas entre varios microservicios. Spring Cloud Sleuth proporciona la infraestructura para que las peticiones salientes envíen un identificativo de correlación de la petición global y para las peticiones entrantes relacionarlo con la petición global.
En una aplicación distribuida con varios microservicios es imprescindible tener la configuración de forma centralizada que cada microservicio obtiene al iniciarse y disponer de registro y descubrimiento para que los servicios al iniciarse, terminarse, actualizarse o por un fallo se registren o desregistren y obtengan la ubicación de las dependencias que necesitan.
Otra de las funcionalidades esenciales en una aplicación distribuida es la trazabilidad de una petición, desde que entra por el API gateway pasando por las diferentes peticiones que hacen los microservicios por la red o envío de mensajes. Es necesaria la funcionalidad que relacione las trazas de todos los servicios para depuración o consulta en un futuro para dar visibilidad a las acciones que se realizan en el sistema.
¿Como se consigue relacionar las trazas de los microservicios que son independientes? La técnica que se emplea es asignar a cada petición entrante un identificativo, más bien un identificativo para la transacción de forma global y un identificativo para la transacción en cada microservicio que varía en cada comunicación de red.
Cuando un microservicio se comunica con otro envía en su petición el identificativo de la transacción global y el de su transacción. Si un microservicio no recibe estos identificativos los genera. En el protocolo HTTP estos identificativos se envían y reciben a través de las cabeceras. Los identificativos permiten correlacionar todas las trazas que emiten los diferentes procesos de los microservicios de una misma petición en la aplicación, haciendo una búsqueda global por el identificativo global se obtiene el conjunto de trazas que han emitido los microservicios por las que ha transitado una petición.
Para obtener mejor visibilidad de los servicios invocados en una transacción y los tiempos y latencias se puede utilizar Zipkin y Prometheus.
En Java el proyecto Spring Cloud Sleuth proporciona la funcionalidad de trazabilidad. En el esquema se observa como Sleuth envía las cabeceras de un servicio cliente a un servicio servidor.
|
|
Sleuth se encarga de propagar las cabeceras del servicio cliente al servicio servidor automáticamente instrumentando los clientes HTTP de RestTemplate, AsyncRestTemplate, WebClient, Apache HttpClient y Netty HttpClient. Para enviar, recibir, obtener y establecer los identificativos de correlación con Sleuth junto con el cliente HTTP de Java hay que hacer la instrumentación manualmente con las clases Tracing y Tracer si no está entre los soportados como en el caso del cliente HTTP que se añadió en Java 11 en el propio JDK con el soporte para HTTP/2.
En la parte servidora Sleuth proporciona un filtro que se encarga de obtener y crear el span de la petición que contiene los identificativos de correlación que con Spring y las dependencias adecuadas se configura automáticamente. Para inyectar y extraer las cabeceras de Sleuth con el cliente HTTP de Java o como en el ejemplo con el de Jersey basta con proporcionar una lambda que realice el añadido o extracción de las cabeceras con la API del cliente.
Ejemplo de microservicio con Spring Boot y Sleuth
Este es el código para instrumentalizar el cliente HTTP de Jersey que utiliza el servicio cliente que invoca al gateway y el código para crear el span en el cliente con los identificativos de correlación y recogerlos en el servicio servidor.
|
|
|
|
He utilizado el ejemplo de la serie de artículos sobre Spring Cloud añadiendo el soporte para Spring Cloud Sleuth. La aplicación se compone de un microservicio de configuración (con Spring Cloud Config), otro de registro y descubrimiento (con Eureka), un servicio de API gateway (con Zuul), el servicio de aplicación y un cliente del servicio que envía las peticiones al gateway y este las redirige al servicio de aplicación.
El cliente inicia un span que es enviado al servidor y el servidor obtiene las cabeceras enviadas. El cliente y el servidor son dos procesos distintos del sistema pero se observa que el identificativo global de la transacción traceId se mantiene en ambos y el identificativo de spanId cambia entre el cliente y el servidor.
|
|
Para iniciar los diferentes microservicios de la aplicación hay que utilizar los siguientes comandos.
|
|
En los proyectos hay que incluir la dependencia para Sleuth en la herramienta de construcción.
|
|
El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:./gradle-run.sh