1 前言
在分布式系统中,往往有着许多服务,又由于请求可能会调用很多个服务以及业务的复杂性,在出现了错误之后,我们可能很难去定位。因此,在微服务架构中,我们需要实现分布式链路监控,去跟进一个请求有哪些服务参与以及它们的调用顺序,从而令每个请求的步骤清晰,在出现问题时可以实现快速定位。
目前链路追踪组件有 Google 的 Dapper,Twitter 的 Zipkin,阿里的 Eagleeye 等,本文将介绍在 Spring Cloud Sleuth 中如何集成 Zipkin。
2 什么是 Spring Cloud Sleuth
Spring Cloud Sleuth 实现了一种分布式的服务链路跟踪解决方案,通过使用 Sleuth 可以让我们快速定位某个服务的问题。
3 术语介绍
3.1 Span
基本工作单元,每当我们发送一个远程调度任务就会产生一个 Span,Span 包含一个64位唯一标识的 ID ,一个64位的 Trace ,以及其他数据信息,比如摘要、时间戳事件、Span 处理者的 ID、以及进度 ID。
3.2 Trace
Trace 是一系列 Span 组成的一个树状结构。调用每个微服务都会产生一个新的 Span,当我们请求一个微服务系统的 API 接口时可能会调用多个微服务,由这个请求产生的 Span 组成了一个 Trace。
3.3 Annotation
用于及时记录存在的事件。
- cs (client send) :客户端发起一个请求,表示 span 开始
- sr (server received):服务器接收到客户端的请求并开始处理,网络延迟 = sr - cs
- ss(server send):服务器处理完请求准备返回数据给客户端,服务器端处理请求花费的时间 = ss - sr
- cr(client received):客户端接收到处理结果,表示 span 结束,客户端接收服务端数据的时间 = cr - cs,整个请求所消耗的时间 = cr - cs
4 代码实战
4.1 服务链路追踪服务端
我们先构建一个服务链路追踪服务端。新建一个项目,命名为 zipkin,其 pom.xml 如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>Zipkin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Zipkin</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- zipkin 界面-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.11.5</version>
</dependency>
<!-- zipkin 服务端-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.11.5</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件
spring.application.name=zipkin
server.port=9411
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
management.metrics.web.server.auto-time-requests=false
spring.main.allow-bean-definition-overriding=true
启动类上需要添加注解 @EnableZipkinServer
package com.example.Zipkin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import zipkin2.server.internal.EnableZipkinServer;
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class ZipkinApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinApplication.class, args);
}
}
4.2 服务链路追踪客户端
我们修改服务提供者 EurekaProducer 项目,将其改造成服务链路追踪客户端,增加一个依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
配置文件修改如下
spring.application.name=producer
server.port=8080
# zipkin的地址
spring.zipkin.base-url=http://localhost:9411
# 设置采样率,为了测试设置100%采集,设置为1.0
spring.sleuth.sampler.probability=1.0
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
我们接下来修改一下服务消费者 EurekaConsumer 项目,增加如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
配置文件修改如下
spring.application.name=consumer
server.port=8082
# zipkin的地址
spring.zipkin.base-url=http://localhost:9411
# 设置采样率,为了测试设置100%采集,设置为1.0
spring.sleuth.sampler.probability=1.0
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
5 zipkin 的图形化数据解析
我们先通过服务消费者远程调用服务提供者几次,然后打开 http://localhost:9411/zipkin/
我们可以看到跟踪信息,每一个框代表一个 Trace我们点开一个 Trace,可以看到多个 Span
点开每个 Span,可以看到详细信息