首先同步下项目概况:前端
上篇文章分享了,路由中间件 - 捕获异常,这篇文章我们分享:路由中间件 - Jaeger 链路追踪。git
啥是链路追踪?github
我理解链路追踪实际上是为微服务架构提供服务的,当一个请求中,请求了多个服务单元,若是请求出现了错误或异常,很难去定位是哪一个服务出了问题,这时就须要链路追踪。api
我们先看一张图:网络
这张图的调用链还比较清晰,我们想象一下,随着服务的愈来愈多,服务与服务之间调用关系也愈来愈多,可能就会发展成下图的状况。架构
这调用关系真的是... 看到这,个人心里是崩溃的。elasticsearch
那么问题来了,这种状况下怎么快速定位问题?分布式
咱们本身也能够设计一个链路追踪,好比当发生一个请求,我们记录它的:ide
请求的惟一标识微服务
请求了哪些服务?
请求的服务依次顺序?
请求的 Request 和 Response 日志?
对日志进行收集、整理,并友好展现
怎么去实现请求的惟一标识?
以 Go 为例 写一个中间件,在每次请求的 Header 中包含:X-Request-Id。
代码以下:
func SetUp() gin.HandlerFunc { return func(c *gin.Context) { requestId := c.Request.Header.Get("X-Request-Id") if requestId == "" { requestId = util.GenUUID() } c.Set("X-Request-Id", requestId) c.Writer.Header().Set("X-Request-Id", requestId) c.Next() } }
每一个 Request 和 Response 日志中都要包含 X-Request-Id。
问题又来了,每次调用都记录日志,当调用的服务过多时,频繁的记录日志,就会有性能问题呀,肿么办?
哎,这么麻烦,看看市面上有没有一些开源工具呢?
Jaeger:https://www.jaegertracing.io
Zipkin:https://zipkin.io/
Appdash:https://about.sourcegraph.com/
这个就很少作介绍了,基本上都能知足需求,至于优缺点,你们能够挨个去瞅瞅,喜欢哪一个就用哪一个?
我为何选择 Jaeger ?
由于我目前只会用这个,其余还不会 ...
我们一块儿看下 Jaeger 是怎么回事吧。
图片来源于官网。
简单介绍下上图三个关键组件:
Agent
Agent是一个网络守护进程,监听经过UDP发送过来的Span,它会将其批量发送给collector。按照设计,Agent要被部署到全部主机上,做为基础设施。Agent将collector和客户端之间的路由与发现机制抽象了出来。
Collector
Collector从Jaeger Agent接收Trace,并经过一个处理管道对其进行处理。目前的管道会校验Trace、创建索引、执行转换并最终进行存储。存储是一个可插入的组件,如今支持Cassandra和elasticsearch。
Query
Query服务会从存储中检索Trace并经过UI界面进行展示,该UI界面经过React技术实现,其页面UI以下图所示,展示了一条Trace的详细信息。
其余组件,你们能够了解下并选择性使用。
图片来源于官网。
怎么操做 Span 呢?Span 有哪些能够调用的 API ?
见下图:
All in one
为了方便你们快速使用,Jaeger 直接提供一个 All in one 包,咱们能够直接执行,启动一套完整的 Jaeger tracing 系统。
启动成功后,访问 http://localhost:16686 就能够看到 Jaeger UI。
独立部署
jaeger-agent
jaeger-collector
jaeger-query
jaeger-ingester
jaeger-operator
jaeger-cassandra-schema
jaeger-es-index-cleaner
spark-dependencies
能够自由搭配,组合使用。
端口:6831
协议:UDP
所属模块:Agent
功能:经过兼容性 Thrift 协议,接收 Jaeger thrift 类型数据
端口:14267
协议:HTTP
所属模块:Collector
功能:接收客户端 Jaeger thrift 类型数据
端口:16686
协议:HTTP
所属模块:Query
功能:客户端前端界面展现端口
分布式追踪系统自己也会形成必定的性能低损耗,若是完整记录每次请求,对于生产环境可能会有极大的性能损耗,通常须要进行采样设置。
固定采样
(sampler.type=const)
sampler.param=1 全采样,
sampler.param=0 不采样;
按百分比采样
(sampler.type=probabilistic)
sampler.param=0.1 则随机采十分之一的样本;
采样速度限制
(sampler.type=ratelimiting)
sampler.param=2.0 每秒采样两个traces;
动态获取采样率
(sampler.type=remote)
这个是默认配置,能够经过配置从 Agent 中获取采样率的动态设置。
接入过程有必定的侵入性;
自己缺乏监控和报警机制,须要结合第三方工具来实现,好比配合Grafana 和 Prometheus实现;
看到这,说的都是理论,你们的内心话多是:
Jaeger 部署
Jaeger 在 Gin 中使用
Jaeger 在 gRPC 中使用
关于实战的分享,我准备整理出 4 个服务,而后实现服务与服务之间进行相互调用,目前 Demo 还没写完...
下篇文章再给你们分享。
https://github.com/xinliangnote/go-gin-api