Skip to content

Commit 8cdce5f

Browse files
committed
Add Doc: [go-gin-api] 路由中间件 - 链路跟踪(Jaeger)
1 parent d6c4783 commit 8cdce5f

File tree

12 files changed

+209
-0
lines changed

12 files changed

+209
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
## 概述
2+
3+
首先同步下项目概况:
4+
5+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_4.png)
6+
7+
上篇文章分享了,路由中间件 - 捕获异常,这篇文章咱们分享:路由中间件 - Jaeger 链路追踪。
8+
9+
啥是链路追踪?
10+
11+
我理解链路追踪其实是为微服务架构提供服务的,当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。
12+
13+
咱们先看一张图:
14+
15+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_2.png)
16+
17+
这张图的调用链还比较清晰,咱们想象一下,随着服务的越来越多,服务与服务之间调用关系也越来越多,可能就会发展成下图的情况。
18+
19+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_3.png)
20+
21+
这调用关系真的是... 看到这,我的内心是崩溃的。
22+
23+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_4.jpeg)
24+
25+
那么问题来了,这种情况下怎么快速定位问题?
26+
27+
## 如何设计日志记录?
28+
29+
我们自己也可以设计一个链路追踪,比如当发生一个请求,咱们记录它的:
30+
31+
- 请求的唯一标识
32+
- 请求了哪些服务?
33+
- 请求的服务依次顺序?
34+
- 请求的 Request 和 Response 日志?
35+
- 对日志进行收集、整理,并友好展示
36+
37+
怎么去实现请求的唯一标识?
38+
39+
**以 Go 为例** 写一个中间件,在每次请求的 Header 中包含:X-Request-Id,代码如下:
40+
41+
```
42+
func SetUp() gin.HandlerFunc {
43+
return func(c *gin.Context) {
44+
requestId := c.Request.Header.Get("X-Request-Id")
45+
if requestId == "" {
46+
requestId = util.GenUUID()
47+
}
48+
c.Set("X-Request-Id", requestId)
49+
c.Writer.Header().Set("X-Request-Id", requestId)
50+
c.Next()
51+
}
52+
}
53+
```
54+
55+
每个 Request 和 Response 日志中都要包含 X-Request-Id。
56+
57+
问题又来了,每次调用都记录日志,当调用的服务过多时,频繁的记录日志,就会有性能问题呀,肿么办?
58+
59+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_5.jpeg)
60+
61+
哎,这么麻烦,看看市面上有没有一些开源工具呢?
62+
63+
## 开源工具
64+
65+
- Jaeger:https://www.jaegertracing.io
66+
- Zipkin:https://zipkin.io/
67+
- Appdash:https://about.sourcegraph.com/
68+
69+
这个就不多做介绍了,基本上都能满足需求,至于优缺点,大家可以挨个去瞅瞅,喜欢哪个就用哪个?
70+
71+
**我为什么选择 Jaeger**
72+
73+
因为我目前只会用这个,其他还不会 ...
74+
75+
咱们一起看下 Jaeger 是怎么回事吧。
76+
77+
## Jaeger 架构图
78+
79+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_6.png)
80+
81+
图片来源于官网。
82+
83+
简单介绍下上图三个关键组件:
84+
85+
**Agent**
86+
87+
Agent是一个网络守护进程,监听通过UDP发送过来的Span,它会将其批量发送给collector。按照设计,Agent要被部署到所有主机上,作为基础设施。Agent将collector和客户端之间的路由与发现机制抽象了出来。
88+
89+
**Collector**
90+
91+
Collector从Jaeger Agent接收Trace,并通过一个处理管道对其进行处理。目前的管道会校验Trace、建立索引、执行转换并最终进行存储。存储是一个可插入的组件,现在支持Cassandra和elasticsearch。
92+
93+
**Query**
94+
95+
Query服务会从存储中检索Trace并通过UI界面进行展现,该UI界面通过React技术实现,其页面UI如下图所示,展现了一条Trace的详细信息。
96+
97+
其他组件,大家可以了解下并选择性使用。
98+
99+
## Jaeger Span
100+
101+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_7.png)
102+
103+
图片来源于官网。
104+
105+
怎么操作 Span 呢?Span 有哪些可以调用的 API ?
106+
107+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_8.png)
108+
109+
## Jaeger 部署
110+
111+
**All in one**
112+
113+
为了方便大家快速使用,Jaeger 直接提供一个 All in one 包,我们可以直接执行,启动一套完整的 Jaeger tracing 系统。
114+
115+
启动成功后,访问 http://localhost:16686 就可以看到 Jaeger UI。
116+
117+
**独立部署**
118+
119+
- jaeger-agent
120+
- jaeger-collector
121+
- jaeger-query
122+
- jaeger-ingester
123+
- jaeger-operator
124+
- jaeger-cassandra-schema
125+
- jaeger-es-index-cleaner
126+
- spark-dependencies
127+
128+
可以自由搭配,组合使用。
129+
130+
## Jaeger 端口
131+
132+
- 端口:6831
133+
- 协议:UDP
134+
- 所属模块:Agent
135+
- 功能:通过兼容性 Thrift 协议,接收 Jaeger thrift 类型数据
136+
137+
138+
- 端口:14267
139+
- 协议:HTTP
140+
- 所属模块:Collector
141+
- 功能:接收客户端 Jaeger thrift 类型数据
142+
143+
144+
- 端口:16686
145+
- 协议:HTTP
146+
- 所属模块:Query
147+
- 功能:客户端前端界面展示端口
148+
149+
## Jaeger 采样率
150+
151+
分布式追踪系统本身也会造成一定的性能低损耗,如果完整记录每次请求,对于生产环境可能会有极大的性能损耗,一般需要进行采样设置。
152+
153+
**固定采样**
154+
155+
(sampler.type=const)
156+
157+
- sampler.param=1 全采样,
158+
- sampler.param=0 不采样;
159+
160+
**按百分比采样**
161+
162+
(sampler.type=probabilistic)
163+
164+
- sampler.param=0.1 则随机采十分之一的样本;
165+
166+
**采样速度限制**
167+
168+
(sampler.type=ratelimiting)
169+
170+
- sampler.param=2.0 每秒采样两个traces;
171+
172+
**动态获取采样率**
173+
174+
(sampler.type=remote)
175+
176+
- 这个是默认配置,可以通过配置从 Agent 中获取采样率的动态设置。
177+
178+
## Jaeger 缺点
179+
180+
- 接入过程有一定的侵入性;
181+
- 本身缺少监控和报警机制,需要结合第三方工具来实现,比如配合Grafana 和 Prometheus实现;
182+
183+
看到这,说的都是理论,大家的心里话可能是:
184+
185+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_9.jpg)
186+
187+
## 实战
188+
189+
- Jaeger 部署
190+
- Jaeger 在 Gin 中使用
191+
- Jaeger 在 gRPC 中使用
192+
193+
![](https://github.com/xinliangnote/Go/blob/master/03-go-gin-api%20%5B文档%5D/images/5_api_10.jpeg)
194+
195+
关于实战的分享,我准备整理出 4 个服务,然后实现服务与服务之间进行相互调用,目前 Demo 还没写完...
196+
197+
下篇文章再给大家分享。
198+
199+
## 源码地址
200+
201+
https://github.com/xinliangnote/go-gin-api
202+
203+
## go-gin-api 系列文章
204+
205+
- [1. 使用 go modules 初始化项目](https://mp.weixin.qq.com/s/1XNTEgZ0XGZZdxFOfR5f_A)
206+
- [2. 规划项目目录和参数验证](https://mp.weixin.qq.com/s/11AuXptWGmL5QfiJArNLnA)
207+
- [3. 路由中间件 - 日志记录](https://mp.weixin.qq.com/s/eTygPXnrYM2xfrRQyfn8Tg)
208+
- [4. 路由中间件 - 捕获异常](https://mp.weixin.qq.com/s/SconDXB_x7Gan6T0Awdh9A)
77.7 KB
Loading
6.38 KB
Loading
72.3 KB
Loading
544 KB
Loading
39.6 KB
Loading
7.92 KB
Loading
65.1 KB
Loading
23.2 KB
Loading
82.1 KB
Loading

0 commit comments

Comments
 (0)