Skip to content

Commit 487415a

Browse files
zhangyuzhangyu
authored andcommitted
添加项目追踪相关文档
1 parent 2864334 commit 487415a

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

ops/server_trace/images/trace-id.png

84.2 KB
Loading
50.7 KB
Loading

ops/server_trace/images/zipkin.png

174 KB
Loading

ops/server_trace/trace.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# 使用Spring Cloud Sleuth和Zipkin进行分布式链路跟踪
2+
3+
## 前言
4+
5+
我们目前采用的是微服务结构,随着业务发展,服务拆分导致系统调用链路愈发复杂,以TMC服务的机票预订流程为例,创建一个订单需要调用tmc-services、basic-resource、domestic-flight-service、flight-dynamic、insurance-service、mail-service、sms-service等多个服务才能完成,当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些服务引起的,这时就需要解决如何快速定位服务故障点,以对症下药。于是就有了分布式系统调用跟踪的诞生。
6+
7+
## 技术选型
8+
9+
**Spring Cloud Sleuth** + **Zipkin** + **Elasticsearch**
10+
11+
Spring Cloud Sleuth主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 Zipkin,我们只需通过添加项目依赖即可实现追踪功能。
12+
13+
- Spring Cloud Sleuth 数据收集
14+
- Elasticsearch 数据存储
15+
- Zipkin 数据展示
16+
17+
## Spring Cloud Sleuth
18+
19+
[Spring Cloud Sleuth](https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.1.0.RELEASE/single/spring-cloud-sleuth.html)为服务之间调用提供链路追踪。通过Sleuth可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而让我们可以很方便的理清各服务间的调用关系。
20+
21+
### 术语
22+
23+
- **Trace**:一系列Span组成的一个树状结构。请求一个服务的API接口,这个API接口,需要调用多个微服务,调用每个微服务都会产生一个新的Span,所有由这个请求产生的Span组成了这个Trace。
24+
25+
- **Span**: 最基本的工作单元。例如: 发送一个RPC就是一个新的span,同样一次RPC的应答也是。Span通过一个唯一的ID来作为标识,另外,再使用一个ID用于服务调用跟踪。Span也可以带有其他数据,例如:描述,时间戳,键值对标签,起始Span的ID,以及处理ID等等。 Span有起始和结束,它们用于跟踪时间信息。Span应该都是成对出现的,有始必有终,所以一旦创建了一个span,那就必须在未来某个时间点结束它。
26+
27+
- **Annotation**: 用于记录一个事件的时间信息。一些基础核心的Annotation用于记录请求的起始和结束时间,例如:
28+
- **cs**: 客户端发送(Client Sent的缩写)。这个annotation表示一个span的起始;
29+
- **sr**: 服务端接收(Server Received的缩写)。表示服务端接收到请求,并开始处理。如果减去`cs`的时间戳,则可以计算出网络传输耗时。
30+
- **ss**: 服务端完成请求处理,应答信息被发回客户端(Server Sent的缩写)。如果减去`sr`的时间戳,则可以计算出服务端处理请求的耗时。
31+
- **cr**: 客户端接收(Client Received的缩写)。标志着Span的结束。客户端成功的接收到服务端的应答信息。如果减去`cs`的时间戳,则可以计算出请求的响应耗时。
32+
33+
下图,通过可视化的方式描述了Span和Trace的概念:
34+
35+
![image](./images/trace-id.png)
36+
37+
### 支持的组件
38+
39+
Spring Cloud Sleuth可以追踪以下10种类型的组件
40+
41+
- Async
42+
- Scheduled
43+
- Messaging
44+
- Hystrix
45+
- Feign
46+
- RestTempate
47+
- Zuul
48+
- RXJava
49+
- WebSocket
50+
51+
`以上组件若想实现追踪功能,必须通过注入的方式交由Spring进行管理,否则无法生效。`
52+
53+
## Zipkin
54+
55+
Zipkin是一个开放源代码分布式的跟踪系统,由Twitter公司开源,提供的功能包括:数据的收集、存储、查找和展现。
56+
57+
每个服务向zipkin报告计时数据,zipkin会根据调用关系通过Zipkin UI生成依赖关系图,显示了每个跟踪请求通过了多少个服务,让开发者可通过一个Web前端轻松的分析数据。
58+
59+
## 案例实战
60+
61+
### 构建Zipkin-Server工程
62+
63+
在程序的启动类Application加上@EnableZipkinServer开启ZipkinServer的功能
64+
65+
```java
66+
@SpringBootApplication
67+
@EnableZipkinServer
68+
public class Application {
69+
70+
public static void main(String[] args) {
71+
SpringApplication.run(Application.class, args);
72+
}
73+
}
74+
```
75+
76+
在配置文件application.yml文件,指定服务名为zipkin-server,端口为xxxx
77+
78+
```java
79+
server:
80+
port: xxxx
81+
spring:
82+
application:
83+
name: zipkin-server
84+
```
85+
86+
### 需要加入追踪功能的服务(这里以tmc-services为例)
87+
88+
在application_dependencies.gradle中加入sleuth、zipkin的依赖
89+
90+
```java
91+
dependencies {
92+
// for service trace
93+
compile('org.springframework.cloud:spring-cloud-starter-sleuth:2.1.0.RELEASE')
94+
// zipkin
95+
compile('org.springframework.cloud:spring-cloud-starter-zipkin')
96+
}
97+
```
98+
99+
修改application.xml,添加使用sleuth、zipkin的相关配置
100+
101+
```java
102+
spring:
103+
application:
104+
name: tmc-services
105+
profiles:
106+
active: dev
107+
zipkin:
108+
base-url: https://dev-zipkin.teyixing.com #设置zipkin-server服务地址
109+
sleuth:
110+
web:
111+
client:
112+
enabled: true
113+
sampler:
114+
probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
115+
```
116+
117+
`这里需要注意的是:采样比例设置越高,对系统消耗越大,现在上线初期请求不多,这样设置没有问题,后期应根据实际情况进行适当调整`
118+
119+
修改logback.xml,更改日志记录格式,加入服务名称、traceID、spanID、parentID等信息
120+
121+
```xml
122+
<?xml version="1.0" encoding="UTF-8"?>
123+
<configuration>
124+
<springProperty scope="context" name="springAppName" source="spring.application.name" />
125+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
126+
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
127+
<pattern>%date [%thread] [serviceId:${springAppName:-}/traceId:%X{traceId}/spanId:%X{spanId}/parentId:%X{parentId}] %-5level %logger{80}.%M - %msg%n</pattern>
128+
</encoder>
129+
</appender>
130+
<appender name="FILE"
131+
class="ch.qos.logback.core.rolling.RollingFileAppender">
132+
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
133+
<FileNamePattern>log/businessDebug.%d{yyyy-MM-dd}.log</FileNamePattern>
134+
<MaxHistory>30</MaxHistory>
135+
</rollingPolicy>
136+
<encoder>
137+
<pattern>%date [%thread] [serviceId:${springAppName:-}/traceId:%X{traceId}/spanId:%X{spanId}/parentId:%X{parentId}] %-5level %logger{80}.%M - %msg%n</pattern>
138+
</encoder>
139+
</appender>
140+
<root>
141+
<level value="DEBUG"/>
142+
<appender-ref ref="FILE"/>
143+
<appender-ref ref="STDOUT"/>
144+
</root>
145+
</configuration>
146+
```
147+
148+
项目启动后,调用一个api,可以在控制台看到
149+
150+
``` log
151+
2019-05-12 05:19:14,220 [http-nio-60028-exec-9] [serviceId:tmc-services/traceId:8b74d4ed976edf83/spanId:8b74d4ed976edf83/parentId:] INFO c.t.tmc.services.application.service.admin.train.AdminTrainApplicationService.getTrainOrderDetail - Get train order: 96214299298631680 detail by staff: 10060
152+
153+
2019-05-12 05:19:14,278 [http-nio-60028-exec-9] [serviceId:tmc-services/traceId:8b74d4ed976edf83/spanId:8b74d4ed976edf83/parentId:] INFO c.t.tmc.services.application.service.admin.train.AdminTrainApplicationService.getTrainOrderDetail - Get train order: 96214299298631680 detail by staff: 10060 successfully
154+
```
155+
156+
可以看到日志里已加入服务Id、traceId、spanId、parentId,每个工作单元发送一次请求就会产生一个spanId,每个请求会产生一个tranceId和多个spanId,根据tranceId和spanId就能分析出一个完整的请求都经历了哪些服务单元。
157+
158+
打开Zipkin查看UI页面
159+
160+
![image](./images/zipkin.png)
161+
162+
能看到请求都经历了哪些服务节点。再点相关连接,可以查看调用顺序,并且还能看到在各个服务节点的处理的时间长度。
163+
164+
![image](./images/zipkin-trace.png)

0 commit comments

Comments
 (0)