Spring Cloud: rastreo distribuido con Sleuth

S

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.

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad