Seguimiento de enlaces de Spring Cloud Sleuth+Zipkin. Notas de seguimiento

objetivo de aprendizaje

inserte la descripción de la imagen aquí
Con la popularidad de la arquitectura de microservicios, los servicios se dividen según diferentes dimensiones y, a menudo, una solicitud debe incluir varios servicios. Las aplicaciones de Internet se basan en diferentes conjuntos de módulos de software. Estos módulos de software pueden ser desarrollados por diferentes equipos, pueden implementarse utilizando diferentes lenguajes de programación y pueden implementarse en miles de servidores en múltiples centros de datos diferentes. Por lo tanto, existe la necesidad de herramientas que puedan ayudar a comprender el comportamiento del sistema y analizar los problemas de rendimiento para que, cuando ocurra una falla, el problema pueda localizarse y resolverse rápidamente. En un sistema de arquitectura de microservicio complejo, casi todas las solicitudes de front-end formarán un enlace de llamada de servicio distribuido complejo.
Una cadena de llamada completa de una solicitud puede ser como se muestra en la siguiente figura:
inserte la descripción de la imagen aquí

Este video sigue el aprendizaje de la mejor
enseñanza de seguimiento de enlaces limit_2021: SpringCloud Family Bucket Sleuth + Zipkin Tutorial: conferencias intensivas sobre puntos de conocimiento básicos . Espero que apoye el video original. Este artículo es un refinamiento de notas después de aprender el video.

1. ¿Qué es el seguimiento de enlaces?

El término "seguimiento de enlaces" se propuso en 2010, cuando Google publicó un artículo de Dapper: Dapper, un sistema de seguimiento para sistemas distribuidos a gran escala , que introdujo el principio de implementación del seguimiento de enlaces distribuidos de desarrollo propio de Google, y también presenta cómo son transparentes a las aplicaciones a bajo costo.
El documento (traducción al chino)
simplemente entiende el seguimiento de enlaces, lo que significa que desde el principio hasta el final de una tarea, todos los sistemas llamados durante el período y el tiempo que consume (lapso de tiempo) se pueden registrar por completo.
De hecho, Dapper era solo un sistema de seguimiento de enlaces de llamadas independiente al principio, y luego evolucionó gradualmente hasta convertirse en una plataforma de monitoreo, y en base a la plataforma de monitoreo, nacieron muchas herramientas, como alerta temprana en tiempo real, protección contra sobrecarga, consulta de datos de índice , etc.
Además de Dapper de Google, existen otros productos muy conocidos, como Eagle Eye de Ali, CAT de Dianping, Zipkin de Twitter, Naver (la empresa matriz del famoso software social LINE) PinPoint y el código abierto doméstico SkyWalking (contribuyó a Apache) y así sucesivamente.

2. ¿Qué es detective?

Spring Cloud Sleuth implementa una solución de rastreo distribuido para Spring Cloud. Compatible con Zipkin, HTrace y otros sistemas de rastreo basados ​​en registros como ELK (Elasticsearch. Logstash, Kibana).
Spring Cloud Sleuth proporciona las siguientes características:

  • 链路追踪: A través de Sleuth, puede ver claramente que una solicitud ha pasado por esos servicios y puede resolver fácilmente la relación de llamadas entre los servicios.
  • 性能分析: A través de Sleuth, puede ver fácilmente el tiempo que lleva cada solicitud de muestreo y analizar qué llamadas de servicio consumen mucho tiempo. Cuando el tiempo que consumen las llamadas de servicio aumenta con el aumento en el número de solicitudes, puede proporcionar ciertos servicios para la expansión del servicio recordatorio.
  • 数据分析,优化链路: Para llamadas frecuentes a un servicio, o llamadas paralelas, etc., se pueden realizar algunas medidas de optimización para el negocio.
  • 可视化错误: Para las excepciones que no son detectadas por el programa, puede verificarlas con Zipkin.

3. Terminología

1. Lapso

La unidad básica de trabajo, una sola cadena de llamadas puede llamarse Span, Dapper registra el nombre del Span y la ID y la ID principal de cada Span, reconstruyendo la relación entre diferentes Spans en un proceso de seguimiento, un rectángulo en la figura El cuadro es un Span, y el front-end es un Span desde el envío de una solicitud hasta la recepción de una respuesta.

inserte la descripción de la imagen aquí

El tramo inicial para comenzar a rastrear se denomina tramo raíz. El Id. del intervalo tiene un valor igual al Id. de seguimiento.

La imagen de arriba es más abstracta, dibujamos una imagen fácil de entender, de la siguiente manera:
inserte la descripción de la imagen aquí

Dapper registra los nombres de tramo, así como cada ID de tramo y el ID de tramo primario, para reconstruir la relación entre diferentes tramos durante un seguimiento. Si un tramo no tiene ID principal, se denomina tramo raíz. Todos los intervalos dependen de un seguimiento específico y comparten una identificación de seguimiento.
La figura muestra la estructura específica de la expansión del módulo de microservicio Help.Call.
inserte la descripción de la imagen aquí

2. Seguimiento

Una estructura de árbol compuesta por una lista de Spans, un Trace se considera como un enlace completo y contiene n Spans múltiples en su interior. Hay una relación de uno a muchos entre Trace y Span, y hay una relación padre-hijo entre Span y Span.
Por ejemplo: el cliente invoca el servicio A, el servicio B, el servicio C y el servicio F, y cada servicio, como C, es un tramo. Si otro subproceso en el servicio C llama a D, entonces D es un subtramo de C. Si otro el hilo en el servicio D llama a E, luego E es un sub-Span de D, y el enlace de C->D->E es un Trace. Si el sistema de seguimiento de enlaces está listo y los datos del enlace están disponibles, con la ayuda de las herramientas de renderizado y análisis front-end, se puede lograr el efecto de la siguiente figura: la
inserte la descripción de la imagen aquí
interfaz visual de zipkin que aprenderemos más adelante es la siguiente:
inserte la descripción de la imagen aquí

3. Anotación

Utilizadas para registrar la existencia de un evento en el tiempo, algunas anotaciones centrales se utilizan para definir el inicio y el final de una solicitud.

  • cs-Client Sent: el cliente inicia una solicitud y esta anotación describe el inicio del tramo;
  • sr-Server Received: el servidor recibe la solicitud y está listo para comenzar a procesarla.Si sr resta la marca de tiempo cs, se puede obtener el retraso de la red;
  • ss-Server Sent: cuando se completa el procesamiento (cuando la solicitud se devuelve al cliente), si ss menos la marca de tiempo sr, se puede obtener el tiempo requerido para que el servidor procese la solicitud;
  • cr-Cliente recibido: indica que el cliente al final del lapso ha recibido con éxito la respuesta del servidor.Si cr resta la marca de tiempo cs, puede obtener todo el tiempo necesario para que el cliente obtenga la respuesta del servidor.

Fórmula:
Network delay = sr - cs
El tiempo requerido para que el servidor procese una solicitud = ss - sr
Todo el tiempo requerido para que el cliente obtenga una respuesta del servidor = cr - cs

4. Principio de implementación

Si desea saber qué enlace de una interfaz tiene un problema, debe saber qué servicios son llamados por la interfaz y el orden de las llamadas. Si encadena estos servicios, se ve como una cadena, a la que llamamos cadena de llamadas .

inserte la descripción de la imagen aquí
Si desea realizar la cadena de llamadas, debe crear un identificador para cada llamada y luego organizar los servicios de acuerdo con el tamaño del identificador, para que pueda ver la secuencia de llamadas con mayor claridad . tiempo siendo .

inserte la descripción de la imagen aquí
En el campo real, necesitamos saber la situación de una determinada llamada de solicitud, por lo que solo el spanid no es suficiente, debemos crear un identificador único para cada solicitud, de modo que podamos averiguar todos los servicios llamados por esta solicitud de acuerdo con el identificador, y llamamos a este identificador como traceid .

inserte la descripción de la imagen aquí
Ahora, de acuerdo con Spanid, el orden de los servicios llamados se puede conocer fácilmente, pero la relación jerárquica de las llamadas no se puede reflejar.Como se muestra en la figura a continuación, los servicios múltiples se pueden llamar cadenas paso a paso, o se pueden llamar por el mismo servicio al mismo tiempo.

inserte la descripción de la imagen aquí
Por lo tanto, debe registrarse quién lo llamó cada vez, usamos parentid como el nombre de esta identificación.
inserte la descripción de la imagen aquí

Hasta ahora, conocemos la secuencia de llamadas y la relación jerárquica, pero después de que la interfaz tiene un problema, todavía no podemos encontrar el enlace problemático.Si hay un problema con un determinado servicio, el servicio llamado debe tomar mucho tiempo. calcule el consumo En este momento, las tres identificaciones anteriores no son suficientes, y también se requiere una marca de tiempo, y la marca de tiempo puede ser más fina, con una precisión de microsegundos.
Agregue la marca de tiempo cuando se inició la solicitud .
inserte la descripción de la imagen aquí
Solo registrar la marca de tiempo cuando se inicia la llamada no requiere mucho tiempo. Es necesario registrar la marca de tiempo cuando el servicio regresa, y la diferencia de tiempo solo se puede calcular desde el principio hasta el final. Dado que la devolución también se registra, escriba abajo las tres marcas anteriores. De lo contrario, no puedo decir de quién es la marca de tiempo.

inserte la descripción de la imagen aquí

Aunque se puede calcular el tiempo total que lleva desde la invocación del servicio hasta la devolución del servicio, este tiempo incluye el tiempo de ejecución del servicio y el retraso de la red. A veces, necesitamos distinguir estos dos tipos de
tiempo para la optimización específica. Entonces, ¿cómo calcular el retraso de la red? Podemos dividir el proceso de llamar y devolver en los siguientes cuatro eventos.

  • Cliente enviado se conoce como cs, y el cliente inicia una solicitud de llamada al servidor.
  • El servidor recibido se conoce como sr. Significa que el servidor ha recibido la solicitud de llamada del cliente.
  • Servidor enviado se conoce como ss, lo que significa que el servidor ha completado el procesamiento y está listo para devolver información al cliente.
  • Cliente recibido se abrevia como cr, lo que significa que el cliente F ha recibido la información de devolución del servidor.

inserte la descripción de la imagen aquí

Si registra la marca de tiempo cuando ocurren estos cuatro eventos, puede calcular fácilmente el tiempo que lleva, por ejemplo:

sr menos cs es el retraso de la red cuando se llama
ss menos sr es el tiempo de ejecución del servicio
cr menos ss es el retraso de la respuesta del servicio
cr menos cs es el tiempo de ejecución de toda la llamada de servicio

inserte la descripción de la imagen aquí
De hecho, además de registrar estos parámetros, también se puede registrar otra información en el lapso, como el nombre del servicio que llama, el nombre del servicio llamado, el resultado de la devolución, la IP, el nombre del servicio que llama, etc. Finalmente, ponemos el tramo con el mismo parentid La información se sintetiza en un bloque de tramo grande y se completa una cadena de llamada completa.

El dibujo del prototipo anterior es del dibujo de Zhang Yinuo.

5. Preparación ambiental

  • servidor eureka: centro de registro
  • eureka-server02: centro de registro
  • servidor de puerta de enlace: puerta de enlace del servicio Spring Cloud Gateway
  • producto-servicio: servicio de productos básicos, que proporciona una interfaz para consultar productos básicos en función de claves principales http://localhost:7870/product/{id} http://localhost:7870/product/listByIds para consultar productos básicos en función de varias claves principales
  • order-service: servicio de pedidos, que proporciona una interfaz para consultar pedidos en función de la clave principal http://localhost:9090/order/{id} y el servicio de pedidos llama al servicio de productos básicos.

Información del curso:
Baidu Cloud-Courseware
Código de extracción: c8cp
inserte la descripción de la imagen aquí
Abra en IDEA
inserte la descripción de la imagen aquí
e importe el proyecto de la siguiente manera:
inserte la descripción de la imagen aquí
Luego comience en orden:
eureka-server
eureka-server2
gateway
order-service
product-service

Agregar configuración al iniciar eureka-server y eureka-server2

register-with-eureka: false #是否将自己注册到eureka中
    fetch-registry: false #是否从eureka中拉去信息列表

inserte la descripción de la imagen aquí
Tenga en cuenta aquí, si hay un subproyecto @SpringBootApplication que informa un problema rojo
inserte la descripción de la imagen aquí
Solución: haga clic con el botón derecho en el proyecto maven-reload
inserte la descripción de la imagen aquí
para verificar si Eureka se inicia correctamente
Visite

http://localhost:8761/

inserte la descripción de la imagen aquí

Verificar si el servicio producto-servicio se inicia con éxito
Visitar

http://localhost:7070/product/listByIds?id=1&id=2

inserte la descripción de la imagen aquí
Verificar si el servicio de atención de pedidos se inició con éxito
Visitar

http://localhost:9090/order/1

inserte la descripción de la imagen aquí
Verifique si la puerta de enlace se inició correctamente
Acceder

http://localhost:9000/order-service/order/1

inserte la descripción de la imagen aquí
acceso

http://localhost:9000/product-service/product/listByIds?id=1&id=2

inserte la descripción de la imagen aquí
no encontré ningún problema

6. Caso introductorio

Agregue dependencias spring-cloud-starter-sleuth a proyectos que requieran seguimiento de enlaces (puerta de enlace de servicios, servicio de productos, servicio de pedidos).

6.1 Agregar dependencias

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

6.2 Registro

Agregue el archivo de registro logback.xml al proyecto que necesita el seguimiento de enlaces (puerta de enlace de servicio, servicio de productos básicos, servicio de pedido), el contenido es el siguiente (el nivel de salida del registro de inicio de sesión debe ser el nivel DEBUG): preste atención para
modificar

< propiedad nombre=“log.path”
value=“${catalina.base}/gateway-server/logs”/ >

en el nombre del proyecto.

Configuración del núcleo de registro:

%d{aaaa-MM-dd HH:mm:ss.SSS}
[${applicationName},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] [%thread] %-5nivel %registrador{50} - %msg%n

Nota: Los archivos de registro provistos en los datos tienen problemas de codificación, solo copie los que tengo aquí
inicio de sesión.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,
则低于WARN的信息都不会输出 -->
<!-- scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默
认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
    <!-- 日志上下文名称 -->
    <contextName>my_logback</contextName>
    <!-- name的值是变量的名称,value的值是变量定义的值。通过定义的值会被插入到logger上下文
中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="${catalina.base}/gateway-server/logs"/>
    <!-- 加载 Spring 配置文件信息 -->
    <springProperty scope="context" name="applicationName"
                    source="spring.application.name" defaultValue="localhost"/>
    <!-- 日志输出格式 -->
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}
[${applicationName},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] [%thread] %-5level
%logger{50} - %msg%n"/>
    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级
别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 输出到文件 -->
    <!-- 时间滚动输出 level为 DEBUG 日志 -->
    <appender name="DEBUG_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_debug.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每个日志文件最大100MB -->
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
            <!-- 日志量最大 10 GB -->
            <totalSizeCap>10GB</totalSizeCap>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 对于类路径以 com.example.logback 开头的Logger,输出级别设置为warn,并且只输出到控
制台 -->
    <!-- 这个logger没有指定appender,它会继承root节点中定义的那些appender -->
    <!-- <logger name="com.example.logback" level="warn"/> -->
    <!--通过 LoggerFactory.getLogger("myLog") 可以获取到这个logger-->
    <!--由于这个logger自动继承了root的appender,root中已经有stdout的appender了,自己这边
又引入了stdout的appender-->
    <!--如果没有设置 additivity="false" ,就会导致一条日志在控制台输出两次的情况-->
    <!--additivity表示要不要使用rootLogger配置的appender进行输出-->
    <logger name="myLog" level="INFO" additivity="false">
        <appender-ref ref="CONSOLE"/>
    </logger>
    <!-- 日志输出级别及方式 -->
    <root level="DEBUG">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="DEBUG_FILE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="WARN_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
</configuration>

Tenga en cuenta aquí que el nombre del proyecto es coherente con el nombre del registro
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

6.3 Acceso

Antes de acceder se debe reiniciar el proyecto que agrego el log,
inserte la descripción de la imagen aquí
luego de reiniciar se encuentra que se genera el archivo
inserte la descripción de la imagen aquí

acceso:

http://localhost:9000/order-service/order/1

El resultado es el siguiente:
El gateway de servicio imprime información:
inserte la descripción de la imagen aquí

[gateway-server,f82de2d68493f0cb,f82de2d68493f0cb]

Información de impresión del servicio de productos básicos
inserte la descripción de la imagen aquí

[product-service,f82de2d68493f0cb,93fc5e739328a597]

Solicitar Servicio Imprimir Información

[order-service,f82de2d68493f0cb,a94f977efaf08f05]

inserte la descripción de la imagen aquí
De la información impresa, podemos saber que
el traceId de todo el enlace es: f82de2d68493f0cb, y
el spanId es: 93fc5e739328a597 y a94f977efaf08f05.

Ver archivos de registro no es un buen método. Cuando haya más y más microservicios, habrá más y más archivos de registro, y el trabajo de consulta será cada vez más problemático. Spring recomienda oficialmente usar Zipkin para el seguimiento de enlaces. Zipkin puede agregar registros y realizar visualizaciones y búsquedas de texto completo.

Siete, use Zipkin para el seguimiento de enlaces

7.1 Qué es Zipkin

inserte la descripción de la imagen aquí
Sitio web oficial de ZIPKIN
ZIPKIN es un sistema de seguimiento de datos en tiempo real distribuido de código abierto (Distributed Tracking System) desarrollado y contribuido por Twitter. Está diseñado en base al documento de Google Dapper. Su función principal es recopilar datos de seguimiento en tiempo real de varios sistemas heterogéneos.

Puede recopilar los datos de seguimiento del enlace de solicitud en cada servidor y ayudarnos a consultar los datos de seguimiento a través de la interfaz Rest API, realizar el monitoreo en tiempo real del sistema distribuido, descubrir oportunamente el problema de aumento de demora en el sistema y encontrar la raíz del cuello de botella de rendimiento del sistema. Además de la interfaz API orientada al desarrollo, también proporciona componentes de interfaz de usuario convenientes.Cada servicio informa datos de tiempo a Zipkin, y Zipkin genera un gráfico de dependencia basado en la relación de llamadas, lo que nos ayuda a buscar información de seguimiento de manera intuitiva y analizar los detalles del enlace de la solicitud. . Zipkin proporciona métodos de almacenamiento de datos conectables: In-Memory, MySql, Cassandra y Elasticsearch.

Existen otras implementaciones más maduras de sistemas de seguimiento distribuido, como Naver's PinPoint, Apache's HTrace, Ali's Hawkeye Tracing, JD's Hydra, Sina's Watchman, Meituan Dianping's CAT, Apache's SkyWalking, etc.
inserte la descripción de la imagen aquí

7.2 Principio de funcionamiento

inserte la descripción de la imagen aquí
Hay cuatro componentes que componen Zipkin:

  • Recopilador: el componente recopilador procesa la información de seguimiento enviada desde el sistema externo y convierte la información al formato Span procesado internamente por Zipkin para respaldar el almacenamiento, el análisis, la visualización y otras funciones posteriores.
  • Almacenamiento: componente de almacenamiento, que procesa la información de seguimiento recibida por el recopilador, almacena la información en la memoria de forma predeterminada y puede modificar la estrategia de almacenamiento para usar otros componentes de almacenamiento, que admitan MySQL, Elasticsearch, etc.
  • Interfaz de usuario web: componentes de interfaz de usuario, aplicaciones de nivel superior implementadas en base a componentes de API, proporcionan páginas web para mostrar cadenas de llamadas y dependencias del sistema en Zipkin, etc.
  • API RESTful: el componente API proporciona una interfaz para que la interfaz web consulte los datos en el almacenamiento.

Zipkin se divide en dos extremos, uno es el servidor Zipkin y el otro es el cliente Zipkin. El cliente también es la aplicación del microservicio. El cliente configurará la dirección URL del servidor. Una vez que se produzca una llamada entre servicios, configurarse en el microservicio.El oyente Sleuth en el servicio escucha y genera la información correspondiente de seguimiento y extensión para enviar al servidor. Hay dos formas de envío, una mediante un bus de mensajes como RabbitMQ y la otra mediante un mensaje HTTP.

7.3 Implementación del servidor

El servidor es un paquete jar ejecutable independiente, la dirección de descarga oficial: dirección de descarga ZIPKIN , use el comando java -jar zipkin.jar para comenzar, el puerto predeterminado es 9411. El paquete jar que descargamos es: zipkin-server-2.20.1-exec.jar.
El paquete jar está incluido en los datos:
inserte la descripción de la imagen aquí

El comando de inicio es el siguiente:

java -jar zipkin-server-2.20.1-exec.jar

inserte la descripción de la imagen aquí
Después del inicio de la siguiente manera:
inserte la descripción de la imagen aquí

acceso:

http://localhost:9411/ 

Los resultados son los siguientes:
la última versión de la interfaz.
inserte la descripción de la imagen aquí
La interfaz de la versión anterior.
inserte la descripción de la imagen aquí

7.4 Implementación del cliente

(1) Agregar dependencias

Agregue dependencias spring-cloud-starter-zipkin a proyectos que requieren seguimiento de enlaces (puerta de enlace de servicio, servicio de productos básicos, servicio de pedidos).

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

(2) Archivo de configuración

Configure la dirección del servidor Zipkin y el método de transmisión de datos en proyectos que requieren seguimiento de enlaces (puerta de enlace de servicio, servicio de productos básicos, servicio de pedidos). La configuración por defecto es la siguiente.

spring:
  zipkin:
    base-url: http://localhost:9411/ # 服务端地址
    sender:
      type: web # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
  sleuth:
    sampler:
      probability: 1.0 # # 收集数据百分比,默认 0.1(10%)

Aquí type:web se envía en forma de mensaje Http y se cambiará a otros métodos más adelante.
inserte la descripción de la imagen aquí
Reinicie el proyecto después de realizar los cambios.
El enlace de la llamada actual es el siguiente:
cliente -> puerta de enlace -> pedido-servicio -> producto-servicio

(3) Acceso

acceso:

http://localhost:9000/order-service/order/1 

El resultado es el siguiente:
inserte la descripción de la imagen aquí

El funcionamiento de la nueva versión es el siguiente: visita:

http://localhost:9411/ 

Filtre los resultados de la búsqueda de clics según el tiempo de la siguiente manera:
inserte la descripción de la imagen aquí
Después de hacer clic, los resultados son los siguientes:

inserte la descripción de la imagen aquí
Visitamos el pedido o el inventario varias veces, aquí zipkin también generará varios datos
inserte la descripción de la imagen aquí
Haga clic en la información de seguimiento correspondiente para ver los detalles del enlace de la solicitud.
inserte la descripción de la imagen aquí
Ver la marca de tiempo
inserte la descripción de la imagen aquí
y también descargar los datos como JSON
inserte la descripción de la imagen aquí

Admite consulta condicional
inserte la descripción de la imagen aquí

A través de las dependencias, puede ver las dependencias de los servicios en el enlace. Y también hay una pantalla dinámica de programación de servicios, con una pequeña bola en movimiento, que es muy fácil de usar.
inserte la descripción de la imagen aquí

El funcionamiento de la versión antigua es el siguiente:
visita:

http://localhost:9411/ 

Haga clic para encontrar los resultados de la siguiente manera:
inserte la descripción de la imagen aquí
Haga clic en la información de seguimiento correspondiente para ver los detalles del enlace de la solicitud.
inserte la descripción de la imagen aquí
A través de las dependencias, puede ver las dependencias de los servicios en el enlace.
inserte la descripción de la imagen aquí

En la actualidad, todas nuestras configuraciones se han ido siempre que se haya ido el reinicio, luego necesitamos almacenar el servicio de seguimiento.

7.5 Almacenamiento de datos de seguimiento

Zipkin Server almacena los datos de seguimiento en la memoria de forma predeterminada. Este método no es adecuado para entornos de producción. Una vez que el servidor se apaga y se reinicia o el servicio falla, los datos históricos desaparecerán. Zipkin admite la modificación de la estrategia de almacenamiento para usar otros componentes de almacenamiento, como MySQL, Elasticsearch, etc.

7.5.1 MySQL

(1) Guión de base de datos

Abra la base de datos MySQL, cree la biblioteca zipkin y ejecute el siguiente script SQL.
Dirección del sitio web oficial: dirección del sitio web oficial

El script está en los datos, simplemente ejecútelo en mysql para
inserte la descripción de la imagen aquí
crear una base de datos

CREATE DATABASE zipkin;
USE zipkin;

Después de ejecutar el script, aparecen 3 tablas
inserte la descripción de la imagen aquí

(2) Implementar el servidor Zipkin

Aquí no puede iniciar el servidor directamente a través de la forma predeterminada del jar, pero debe agregar parámetros de inicio y volver a implementar el servidor:
Dirección del sitio web oficial: servidor Zipkin para MySql

java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin

inserte la descripción de la imagen aquí

(3).Prueba

acceso:

http://localhost:9000/order-service/order/1 

Vea los resultados de la base de datos de la siguiente manera:
inserte la descripción de la imagen aquí

En el modo MySQL, cada vez que se inicia el servidor, el servidor cargará la información del enlace de la base de datos y la mostrará en la interfaz web.
Usamos CTRL + C, esc para salir de Zipkin, y luego accedemos al servidor zipkin en este momento, y encontramos que no se puede acceder. ¿Se perdieron los datos anteriores? Reiniciemos el servidor zipkin para ver
inserte la descripción de la imagen aquí
Acceso

http://localhost:9411/zipkin/

Se comprobó que la información de acceso anterior no se perdía porque estaba guardada en mysql
inserte la descripción de la imagen aquí

7.5.2 RabbitMQ

En el curso anterior, aprendimos el uso detallado de RabbitMQ, por lo que no entraremos en detalles aquí, solo comience y utilícelo directamente.

El modo de enlace actual es:
cliente

(1) Inicie el servidor RabbitMQ

Inicie la máquina virtual e inicie el servidor RabbitMQ con el siguiente comando.

systemctl start docker
docker start mq

acceso

ip:15672

Ingrese a la interfaz gráfica de mq y encuentre que no hay cola en este momento
inserte la descripción de la imagen aquí

(2) Implementar el servidor Zipkin

Agregue parámetros de inicio y vuelva a implementar el servidor:
dirección del sitio web oficial: sitio web oficial deployment-mq

java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/ --RABBIT_QUEUE=zipkin

Los parámetros de inicio incluyen la configuración de MySQL y RabbitMQ, que se basa en MQ y almacena información de enlace a MySQL, como se muestra en la siguiente figura:

inserte la descripción de la imagen aquí

(3) Revisa la cola

Visite: http://192.168.10.101:15672/#/queues Puede ver que se ha creado la cola zipkin.
inserte la descripción de la imagen aquí
Aquí, para ver el proceso de consumo de mensajes, detenemos el servidor y limpiamos las tablas de la base de datos zipkin en mysql.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

(4) Los clientes agregan dependencias

Documentos del sitio web oficial: los documentos oficiales
se agregan en puertas de enlace, servicios de pedidos y servicios de productos

<!-- 消息队列通用依赖 -->
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
        </dependency>

(5) Archivo de configuración del cliente

aplicación.yml

spring:
  application:
    name: gateway-server # 应用名称
  cloud:
    gateway:
      discovery:
        locator:
          # 是否与服务发现组件进行结合,通过 serviceId 转发到具体服务实例。
          enabled: true                  # 是否开启基于服务发现的路由规则
          lower-case-service-id: true    # 是否将服务名称转小写
  zipkin:
    base-url: http://localhost:9411/ # 服务端地址
    sender:
      # ype: web # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
      type: rabbit # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
  sleuth:
    sampler:
      probability: 1.0 # # 收集数据百分比,默认 0.1(10%)
  rabbitmq:
    host: 192.168.10.101
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    listener:
      direct:
        retry:
          enabled: true
          max-attempts: 5
          initial-interval: 5000
      simple:
        retry:
          enabled: true
          max-attempts: 5
          initial-interval: 5000

inserte la descripción de la imagen aquí
Reiniciar el servicio después de la configuración

(6).Prueba

Primero cierre el servidor Zipkin, visite:

http://localhost:9000/order-service/order/1 

El cliente ha escrito datos de seguimiento de enlaces en la cola:

Después de iniciar el servidor Zipkin, los mensajes en la cola se acumulan.
inserte la descripción de la imagen aquí
Ahora volvemos a iniciar el servidor Zipkin.

java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/ --RABBIT_QUEUE=zipkin

Los mensajes en la cola se consumen después del inicio
inserte la descripción de la imagen aquí

Los datos de seguimiento de enlaces se almacenan en MySQL.
inserte la descripción de la imagen aquí

7.5.3 Búsqueda elástica

Hemos aprendido el uso detallado de Elasticsearch en el curso anterior, por lo que no entraremos en detalles aquí, solo comience y utilícelo directamente.

(1) Inicie el clúster de Elasticsearch

Para iniciar el clúster, visite:

http://192.168.10.101:9200/ 

El resultado es el siguiente:
inserte la descripción de la imagen aquí

Inicie el complemento principal, visite: http://192.168.10.101:9100/ Los resultados son los siguientes:
inserte la descripción de la imagen aquí

(2) Implementar el servidor Zipkin

Agregue parámetros de inicio y vuelva a implementar el servidor:
Dirección del sitio web oficial: Servidor Zipkin

java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=http://192.168.10.101:9200/,http://192.168.10.102:9200/,http://192.168.10.103:9200/ --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_QUEUE=zipkin

Los parámetros de inicio incluyen la configuración de Elasticsearch y RabbitMQ, que se basa en MQ y almacena información de enlaces a Elasticsearch.

(3) Ver la biblioteca de índice

Visite: http://192.168.10.101:9100 Puede ver que se ha creado la biblioteca de índice zipkin.
inserte la descripción de la imagen aquí

(4) Los clientes agregan dependencias

Documentos del sitio web oficial: documentos oficiales

<!-- 消息队列通用依赖 -->
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
</dependency>

(5) Archivo de configuración del cliente

spring:
 zipkin:
   base-url: http://localhost:9411/ # 服务端地址
   sender:
     type: rabbit
   rabbitmq:
     queue: zipkin                  # 队列名称
 rabbitmq:
   host: 192.168.10.101             # 服务器 IP
   port: 5672                       # 服务器端口
   username: guest                  # 用户名
   password: guest                  # 密码
   virtual-host: /                  # 虚拟主机地址
   listener:
     direct:
       retry:
         enabled: true              # 是否开启发布重试
         max-attempts: 5            # 最大重试次数
         initial-interval: 5000     # 重试间隔时间(单位毫秒)
     simple:
       retry:
         enabled: true              # 是否开启消费者重试
         max-attempts: 5            # 最大重试次数
         initial-interval: 5000     # 重试间隔时间(单位毫秒)
 sleuth:
   sampler:
     probability: 1.0               # 收集数据百分比,默认 0.1(10%)

(6).Prueba

acceso:

http://localhost:9000/order-service/order/1 

Vea los resultados de la biblioteca de índices de la siguiente manera:
inserte la descripción de la imagen aquí

8. Usa ELK para analizar y rastrear datos

ELK es un conjunto completo de soluciones de recopilación y visualización de registros proporcionado por la empresa elástica. Es el acrónimo de tres productos, a saber, ElasticSearch, Logstash y Kibana.

  • Elasticsearch ES para abreviar : un motor de búsqueda y análisis distribuido en tiempo real, que se puede utilizar para búsquedas de texto completo, búsquedas estructuradas y análisis. Un motor de búsqueda basado en el motor de búsqueda de texto completo Apache Lucene, escrito en lenguaje Java.
  • Logstash : un motor de recopilación de datos con capacidades de transmisión en tiempo real, que recopila, analiza y envía varios datos a ES. Escrito en lenguaje Ruby.
  • Kibana : proporciona una plataforma web de análisis y visualización para Elasticsearch. Puede buscar en el índice de Elasticsearch, interactuar con los datos y generar varias tablas y gráficos de dimensiones.
  • Beats : un término colectivo para un grupo de programas de adquisición ligeros escritos en el lenguaje Go. Los siguientes son los 5 tipos de ritmos admitidos oficialmente por elastic. De hecho, el gran poder del código abierto ya ha creado docenas o incluso cientos de tipos de ritmos, que solo son inesperados para usted y no se pueden hacer sin ritmos:
    • Filebeat: recopila archivos y directorios, principalmente para recopilar datos de registro.
    • Winlogbeat: recopilación de datos específicamente para el registro de eventos de Windows.
    • Metricbeat: para recopilar indicadores, los indicadores pueden ser del sistema o de muchos productos de software intermedio, que se utilizan principalmente para monitorear el rendimiento del sistema y el software.
    • Packetbeat: a través de la captura de paquetes de red y el análisis de protocolos, el monitoreo y la recopilación de datos de algunas comunicaciones del sistema de solicitud-respuesta pueden recopilar una gran cantidad de información que no se puede recopilar mediante métodos convencionales.
    • Heartbeat: Detección de conectividad entre sistemas, como monitoreo de conectividad de icmp, tcp, http y otros sistemas.

8.1 Preparación del entorno

Ya hemos aprendido el uso detallado de ELK en el curso anterior, por lo que no entraremos en detalles aquí, solo comience y utilícelo directamente. La versión ELK utilizada en este artículo es uniformemente 7.5.2.

  • Las direcciones de clúster de Elasticsearch utilizadas en este artículo son:
    192.168.10.101:9200
    192.168.10.102:9200
    192.168.10.103:9200
  • La dirección de Logstash utilizada en este artículo es:
    192.168.10.101:9250
  • La dirección de Kibana utilizada en este artículo es:
    192.168.10.101:5601

El contenido del archivo de configuración log-to-es.conf especificado cuando se ejecuta Logstash es el siguiente:

# 数据入口
input {
 tcp {
 mode => "server"
 host => "192.168.10.101"
 port => 9250
 }
}
# 处理数据
filter {
 # 获取 @timestamp 的值并加上 8*60*60(北京时间比 logstash 中@timestamp 晚了 8 小
时),然后赋值给变量 timestamp。
 ruby { 
 code => "event.set('timestamp', event.get('@timestamp').time.localtime + 
8*60*60)"
}
 # 将 timestamp 值重新赋值给 @timestamp
 ruby {
 code => "event.set('@timestamp', event.get('timestamp'))"
 }
 # 删除变量 timestamp
 mutate {
 remove_field => ["timestamp"]
 }
}
# 数据出口
output {
 elasticsearch {
 hosts => ["192.168.10.101:9200", "192.168.10.102:9200", 
"192.168.10.103:9200"]
 index => "applog"
 }
}

8.2 Agregar dependencias

Agregue dependencias logstash-logback-encoder a proyectos que requieran seguimiento de enlaces (puerta de enlace de servicio, servicio de producto, servicio de pedido).

<!-- logstash 编码依赖 -->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>6.3</version>
</dependency>

8.3 Configuración de registro

Agregue logstash a los datos de salida en formato JSON en proyectos que requieren seguimiento de enlaces (puerta de enlace de servicio, servicio de productos básicos, servicio de pedidos).
inicio de sesión.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
    
   ...
    <!-- 为 Logstash 输出 JSON 格式数据 -->
    <appender name="LOGSTASH_PATTERN"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <!-- 数据输出目的地 -->
        <destination>192.168.10.101:9250</destination>
        <!-- 日志输出编码 -->
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <pattern>
                    <pattern>
                       {
                       "severity": "%level",
                       "service": "${springAppName:-}",
                       "trace": "%X{X-B3-TraceId:-}",
                       "span": "%X{X-B3-SpanId:-}",
                       "exportable": "%X{X-Span-Export:-}",
                       "pid": "${PID:-}",
                       "thread": "%thread",
                       "class": "%logger{40}",
                       "rest": "%message"
                       }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    <!-- 日志输出级别及方式 -->
    <root level="DEBUG">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="LOGSTASH_PATTERN"/>
        <appender-ref ref="DEBUG_FILE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="WARN_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
    
   ...
</configuration>

8.4 Ver biblioteca de índices

Visite: http://192.168.10.101:9100 Puede ver que se ha creado la biblioteca de índice de applog.
inserte la descripción de la imagen aquí

8.5 Pruebas

Visite: http://localhost:9000/order-service/order/1 Los resultados de la biblioteca de índice son los siguientes:
inserte la descripción de la imagen aquí
Visite: http://192.168.10.101:5601/ Página de inicio de Kibana
inserte la descripción de la imagen aquí
Agregar biblioteca de índice de applog.
inserte la descripción de la imagen aquí
No se utiliza ningún filtro de tiempo.
inserte la descripción de la imagen aquí
Los resultados de la puerta de enlace de búsqueda son los siguientes:
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/sinat_38316216/article/details/129926266
Recomendado
Clasificación