Spring Cloud: rastreo distribuido con Sleuth

    Visi贸n general

    En este art铆culo, te presentaremos Spring Cloud Sleuth, que es un marco de seguimiento distribuido para una arquitectura de microservicio en el ecosistema Spring.

    En una arquitectura de microservicio t铆pica, tenemos muchas aplicaciones peque帽as implementadas por separado y, a menudo, necesitan comunicarse entre s铆. Uno de los desaf铆os que enfrentan los desarrolladores es rastrear una solicitud completa de registros depurar o comprobar latencia en servicios downstream.

    Para aumentar a煤n m谩s la complejidad, algunos servicios pueden tener varias instancias en ejecuci贸n. Es dif铆cil rastrear registros de solicitudes particulares en m煤ltiples servicios, especialmente si un servicio en particular tiene muchas instancias.

    Spring Cloud Sleuth agrega autom谩ticamente algunos rastros / metadatos a sus registros y comunicaci贸n entre servicios (a trav茅s de encabezados de solicitud) por lo que es f谩cil rastrear una solicitud a trav茅s de agregadores de registros como Zipkins, ELK, etc.

    Este art铆culo asume que ya tiene conocimiento de los componentes b谩sicos de Spring Cloud. Hemos publicado varios art铆culos que cubren Spring Cloud si desea leer m谩s:

    • Spring Cloud: descubrimiento de servicios con Eureka
    • Spring Cloud: enrutamiento con Zuul y Gateway
    • Nube de Spring: Hystrix
    • Spring Cloud: Turbina

    Preparar

    Para demostrar el concepto de rastreo, usaremos algunos servicios:

    • Servidor Eureka: Act煤a como un registro de servicios y se ejecuta en el puerto 8761.
    • Servicio de direcci贸n: Un servicio REST simple que tiene un 煤nico punto final de /address/{customerId} y corriendo en el puerto 8070.
    • Servicio al Cliente: Un servicio REST simple que tiene un 煤nico punto final de /customer/{customerId} y corriendo en el puerto 8060.
    • Servicio de portal: Un servicio REST simple que tiene un 煤nico punto final de /fullDetails/{customerId} y corriendo en el puerto 8050. Este servicio llama internamente address-service y customer-service para obtener datos y combinarlos antes de la respuesta.
    • Puerta: 脷nico punto de entrada a nuestra arquitectura de microservicio, compilado con Spring Cloud Gateway y ejecut谩ndose en el puerto 8080.

    Y as铆 es como se ve el servidor Eureka cuando todos los servicios est谩n en ejecuci贸n:

    Veamos qu茅 est谩 escrito en cada clase de controlador, comenzando por AddressController del address-service:

    @RestController  
    @RequestMapping(value = "/address")  
    public class AddressController {  
      
        private static Logger log = LoggerFactory.getLogger(AddressController.class);  
      
        @GetMapping(value = "/{customerId}")  
        public String address(@PathVariable(name = "customerId", required = true) long customerId) {  
            log.info("GET /address/"+customerId);  
            return "Address of id="+customerId;  
        }  
    }
    

    CustomerController de customer-service:

    @RestController  
    @RequestMapping(value = "/customer")  
    public class CustomerController {  
      
        private static Logger log = LoggerFactory.getLogger(CustomerController.class);  
      
        @GetMapping(value = "/{customerId}")  
        public String address(@PathVariable(name = "customerId", required = true) long customerId){  
            log.info("GET /customer/"+customerId);  
            return "Customer details of id="+customerId;  
        }  
    }
    

    PortalController de portal-service:

    @RestController
    public class PortalController {
    
        private static Logger log = LoggerFactory.getLogger(PortalController.class);
    
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping(value = "/fullDetails/{customerId}")
        public String address(@PathVariable(name = "customerId", required = true) long customerId) {
            log.info("GET /fullDetails/" + customerId);
    
            String customerResponse = restTemplate.getForObject("http://customer-service/customer/" + customerId, String.class);
            String addressResponse = restTemplate.getForObject("http://address-service/address/" + customerId, String.class);
    
            return customerResponse + "<br>" + addressResponse;
        }
    }
    

    Para comprobar, ejecutemos el portal-service punto final a trav茅s de gateway navegando en su navegador a http: // localhost: 8080 / portal-service / fullDetails / 12. Deber铆a ver algo como esto:

    Ahora, imagine rastrear estos registros en diferentes servidores. Adem谩s, incluso si tiene estos archivos de registro en una ubicaci贸n com煤n y tiene un agregador de registros, ser铆a dif铆cil encontrar un rastro completo de una solicitud entre varios servicios en alg煤n momento.

    A帽adiendo Spring Cloud Sleuth

    Spring Cloud Sleuth agrega ID 煤nicos a sus registros, que permanecen iguales entre muchos microservicios y pueden ser utilizados por agregadores de registros comunes para ver c贸mo fluye una solicitud.

    Para agregar esta funcionalidad, necesitamos agregar una dependencia en el pom.xml archivo de cada servicio posterior:

    <dependency>  
     <groupId>org.springframework.cloud</groupId>  
     <artifactId>spring-cloud-starter-sleuth</artifactId>  
    </dependency>
    

    Reinicie toda la aplicaci贸n y presione el http: // localhost: 8080 / portal-service / fullDetails / 12 endpoint nuevamente y verifique los registros de cada servicio.

    Portal service registros:

    Address service registros:

    Customer service registros:

    Spring Cloud Sleuth agrega dos tipos de ID a su registro:

    • ID de seguimiento: Un ID 煤nico que permanece igual en toda la solicitud que contiene varios microservicios.
    • ID de extensi贸n: Un ID 煤nico por microservicio.

    B谩sicamente, un ID de seguimiento contendr谩 varios ID de intervalo que pueden ser utilizados f谩cilmente por herramientas de agregaci贸n de registros.

    Sleuth no solo agrega estos ID a nuestros registros, sino que tambi茅n los propaga a las siguientes llamadas de servicio (basadas en HTTP o MQ). Adem谩s, puede enviar registros de muestra aleatorios a aplicaciones externas como Zipkins de forma inmediata.

    Agregaci贸n de registros con Zipkins

    Zipkins es un sistema de seguimiento distribuido que se suele utilizar para solucionar problemas de latencia en arquitecturas de servicios.

    Para ejecutar un servidor Zipkin, puede seguir una gu铆a r谩pida y sencilla aqu铆.

    Us茅 la forma de Java para ejecutarlo, ejecutando los comandos:

    $ curl -sSL https://zipkin.io/quickstart.sh | bash -s
    $ java -jar zipkin.jar
    

    Aunque tambi茅n puede ejecutarlo a trav茅s de Docker o directamente desde el c贸digo fuente.

    De forma predeterminada, el servidor Zipkin se ejecutar谩 en el puerto 9411. Navegue su navegador a http: // localhost: 9411 / zipkin /, para acceder a su p谩gina de inicio:

    Integraci贸n de detective con Zipkins

    Ahora, tenemos que decirle a Sleuth que env铆e datos al servidor Zipkin. Primero necesitamos agregar otra dependencia a la pom.xml archivo de cada servicio:

    <dependency>  
     <groupId>org.springframework.cloud</groupId>  
     <artifactId>spring-cloud-starter-zipkin</artifactId>  
    </dependency>
    

    Despu茅s de esto, necesitamos agregar las siguientes propiedades en el application.properties archivo de cada servicio:

    spring.sleuth.sampler.probability=100  
    spring.zipkin.baseUrl= http://localhost:9411/
    

    los spring.zipkin.baseUrl La propiedad le dice a Spring y Sleuth d贸nde enviar los datos. Adem谩s, de forma predeterminada, Spring Cloud Sleuth establece todos los intervalos en no exportables. Esto significa que estas trazas (Trace Id y Span Id) aparecen en los registros pero no se exportan a otra tienda remota como Zipkin.

    Para exportar tramos al servidor Zipkin, necesitamos establecer una tasa de muestreo usando spring.sleuth.sampler.probability. Un valor de 100 significa que todos los intervalos tambi茅n se enviar谩n al servidor Zipkin.

    Ahora, reiniciemos todas las aplicaciones nuevamente y presionemos el http: // localhost: 8080 / portal-service / fullDetails / 12 punto final de nuevo.

    Ahora, en la p谩gina de inicio de Zipkin en http: // localhost: 9411 / zipkin /, haga clic en “Buscar rastros”:

    Al hacer clic en un rastro, se nos dirigir谩 a su p谩gina de detalles:

    Arriba podemos ver que la solicitud en general tom贸 alrededor de 16 ms y un 谩rbol que muestra el tiempo que tom贸 cada servicio.

    Normalmente, para visualizar registros con fines de depuraci贸n, utilizamos la pila ELK. Para integrarlo con Sleuth podemos seguir la explicaci贸n aqu铆.

    Conclusi贸n

    En este art铆culo, hemos cubierto c贸mo usar Spring Cloud Sleuth en nuestra aplicaci贸n de microservicio existente basada en Spring. Vimos c贸mo es 煤til para el seguimiento de registros de una sola solicitud que abarca varios servicios. Tambi茅n lo integramos con un servidor Zipkin para ver la latencia de cada subservicio en la solicitud y respuesta general.

    Como siempre, el c贸digo de los ejemplos utilizados en este art铆culo se puede encontrar en Github.

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *