I. Application Scenario of Distributed Link Tracing Technology (Problem Scenario)

1. Scenario description

In the microservice architecture, a request can be completed at least three or four service invocations, and at most it can span dozens or even hundreds of service nodes. The questions then arise:

  • How to dynamically display the invocation link of a service? (such as what other services A service calls – dependencies)
  • How do you analyze and tune bottleneck nodes in service invocation links? (For example, A — >B — >C, where the C service takes A very long time)
  • How can I quickly discover faults on service links?

2. Distributed link tracking technology

The monitoring technology based on this idea in a distributed environment is distributed link tracing (full link tracing)

3. Distributed link tracing solutions on the market

  • Spring Cloud Sleuth + Twitter Zipkin(most active community, most well-documented)
  • Alibaba’s Eagle Eye
  • “CAT” of Dianping
  • Meituan “Mtrace”
  • Jingdong “Hydra”
  • Sina’s “Watchman”
  • Apache Skywalking (mentioned a lot lately)

Second, the core idea of distributed link tracking technology

Nature: Logging, as a complete technology, distributed link tracing also has its own theory and concept

In the microservice architecture, the call chain for request processing can be represented as a tree, as shown below:


The preceding figure shows a request link. A link is uniquely identified by TraceId. A SPAN identifies the request information

Trace: Request -> Response

Trace ID: The service tracing framework creates a unique Trace ID for this request and retains this unique Trace ID as it flows through the distributed system until it is returned to the requester

SpanID: In order to count the time delay of each processing unit, when a request arrives at each service component, it is also marked with a unique SpanID to mark its start, process, and end. For each Span, it must have two start and end nodes. By recording the timestamp of the start Span and the end Span, the time delay for that Span can be calculated. In addition to the timestamp record, it can also contain some other metadata, such as the time name, request information, etc. Each Span has a unique trace identifier Span ID, and several ordered spans form a trace.


Span can be considered as a log data structure, which records some log information at some special time points, such as timestamp, spanId, TraceId, parentIde, etc. Another concept is abstracted from Span, called event, and the core event is as follows:

  • CS: Client send/start A client/consumer sends a request that describes the start of a span
  • SR: Server received/start The sr-CS is the network delay of sending requests
  • SS: Server send/ Finish The SS-SR indicates the time consumed by the server
  • CR: Client received/ FINISHED Cr-SS Indicates the response time (network delay of the response).

Note: We often use Spring Cloud Sleuth and Zipkin together, send Sleuth data information to Zipkin for aggregation, and use Zipkin to store and display data.


Sleuth + Zipkin

  1. Every microservice project that needs to be tracked introduces dependency coordinates
<! -- Link Tracing -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
Copy the code
  1. Each microservice modifies the application.yml configuration file to add a log level
# Distributed link tracing
logging:
  level:
    org.springframework.web.servlet.DispatcherServlet: debug
    org.springframework.cloud.sleuth: debug
Copy the code

When the request comes in, we can observe the logs (global TraceId, SpanId, and so on) that Sleuth outputs on the console.

  1. Display tracking data with Zipkin

Zipkin consists of Zipkin Server and Zipkin Client. Zipkin Server is an independent service, and Zipkin Client is a specific micro-service

Zipkin Server build:

  • pom.xml
<dependencies>
        <! -- Zipkin-server dependencies -->
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
 <version>2.12.3</version>  <exclusions>  <! Log4j2 = log4j2 = log4j2 = log4j2 = log4j2 = log4j2  <exclusion>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-log4j2</artifactId>  </exclusion>  </exclusions>  </dependency>   <! -- Zipkin-server UI depends on coordinates -->  <dependency>  <groupId>io.zipkin.java</groupId>  <artifactId>zipkin-autoconfigure-ui</artifactId>  <version>2.12.3</version>  </dependency>    <! Mysql persistence dependency -->  <dependency>  <groupId>io.zipkin.java</groupId>  <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>  <version>2.12.3</version>  </dependency>  <dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  </dependency>  <dependency>  <groupId>com.alibaba</groupId>  <artifactId>druid-spring-boot-starter</artifactId>  <version>1.1.10</version>  </dependency>  <! -- Transaction control required to operate database -->  <dependency>  <groupId>org.springframework</groupId>  <artifactId>spring-tx</artifactId>  </dependency>  <dependency>  <groupId>org.springframework</groupId>  <artifactId>spring-jdbc</artifactId>  </dependency>  </dependencies> Copy the code
  • Entry start class
@SpringBootApplication
@EnableZipkinServer // Enable the Zipkin server function
public class ZipkinServerApplication9411 {

    public static void main(MysqlxDatatypes.Scalar.String[] args) {
 SpringApplication.run(ZipkinServerApplication9411.class,args);  }   // Inject the transaction controller  @Bean  public PlatformTransactionManager transactionManager(DataSource dataSource) {  return new DataSourceTransactionManager(dataSource);  } } Copy the code
  • application.yml
server:
  port: 9411
management:
  metrics:
 web:
 server:  auto-time-requests: false # Disable automatic detection Copy the code

Zipkin Client build:

  • Add Zipkin dependencies to POM (modified in specific microservices)
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
Copy the code
  • Add a reference to Zipkin Server in application.yml
spring:
  application:
    name: lagou-service-autodeliver
  zipkin:
 base-url: http://127.0.0.1:9411/ # zipkin server request address
 sender:  type: web By default, tracking data is sent to Zipkin Server using HTTP  sleuth:  sampler:  The default value is 0.1, that is, 10%, where 1 is set to record all sleUTH information in order to collect more data (for testing only). In distributed systems, too frequent sampling can affect system performance, so the configuration needs to use an appropriate value.  probability: 1.0 Copy the code
  • For log logs, the DEBUG state is still enabled

The Zipkin Server page allows you to view service invocation dependencies and some performance metrics and exception information


Zipkin persists tracking data to mysql

  • Mysql > create a zipkin database and execute the following SQL statement (github zipkin stronge)
  • Pom.xml introduces dependencies
  <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-autoconfigure-storagemysql</
      artifactId>
      <version>2.12.3</version>
 </dependency>  <dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  </dependency>  <dependency>  <groupId>com.alibaba</groupId>  <artifactId>druid-spring-boot-starter</artifactId>  <version>1.1.10</version>  </dependency>  <dependency>  <groupId>org.springframework</groupId>  <artifactId>spring-tx</artifactId>  </dependency>  <dependency>  <groupId>org.springframework</groupId>  <artifactId>spring-jdbc</artifactId>  </dependency> Copy the code
  • application.yml
server:
  port: 9411
management:
  metrics:
 web:
 server:  auto-time-requests: false # Disable automatic detection spring:  datasource:  driver-class-name: com.mysql.jdbc.Driver  url: jdbc:mysql://localhost:3306/zipkin? useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true  username: root  password: 123456  druid:  initialSize: 10  minIdle: 10  maxActive: 30  maxWait: 50000 # specify mysql as the zipkin persistence medium zipkin:  storage:  type: mysql Copy the code
  • The transaction manager is injected into the startup class
@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
  return new DataSourceTransactionManager(dataSource);
}
Copy the code

Summary of lagouedu notes

This article is formatted using MDNICE