背景
微服务架构带来很多益处的同时也让零碎的复杂度晋升了,传统的单体利用依照不同的维度拆分成一个一个散布式微服务,不同的微服务甚至可能采纳不同的语言编写;此外,服务的部署往往都是分布式的,可能有几千台服务器,横跨多个不同的城市数据中心。下图是一个典型的微服务架构,图中的节点数还比拟少,在支付宝,一个线下领取整体交易付款链路,波及上百个节点。
图片起源:https://www.splunk.com/en_us/data-insider/what-is-distributed-tracing.html#benefits-of-distributed-tracing
微服务化引入了以下几个典型问题:
- 故障定位难,一次申请往往须要波及到多个服务,排查问题甚至须要拉上多个团队
- 残缺调用链路梳理难,节点调用关系剖析
- 性能剖析难,性能短板节点
以上这几个问题其实都是利用的可观测性问题:
- log
- Trace
- metrics
本文将会专一于 Trace 方面,残缺地说是分布式链路跟踪 (Distributed tracing)。2010 年谷歌发表了 Dapper 的论文,分享了他们的解决方案,算是业界比拟早的分布式链路追踪零碎。之后各大互联网公司纷纷参照 Dapper 的思维推出各自的链路跟踪零碎,包含 Twitter 的 Zipkin、阿里的鹰眼,还有 PinPoint,Apache 的 HTrace 和 Uber 的 Jaeger;当然,也有咱们的本文的配角:SOFATracer。分布式链路的实现有多种多样,因而也催生了分布式链路追踪的标准:OpenTracing,2019 年 OpenTracing 和 OpenCensus 合并成为了 OpenTelemetry。
OpenTracing
在深刻 SOFATracer 之前先简略解释一下 OpenTracing,因为 SOFATTracer 是基于 OpenTracing 标准(基于 0.22.0 的 OpenTracing,新版的标准 API 有所不同)构建的。一个 Trace 由服务调用生成的 Span 及其之间的援用形成,一个 Span 是一个时间跨度,一次服务调用创立一个新 Span,分为调用 Span 和被调 Span,每个 Span 蕴含:
- TraceId and SpanId
- 操作名称
- 耗时
- 服务调用后果
一个 Trace 链路中个别会有多个服务调用,那么也就会有多个 Span,Span 之间的关系由援用申明,援用从调用者指向服务提供者,OpenTracing 中指定了两个援用类型:
- ChildOf,同步服务调用,客户端须要服务端的后果返回能力进行后续解决;
- FollowsFrom,异步服务调用,客户端不期待服务端后果。
一个 Trace 是一个有向无环图,一次调用的拓扑能够如下展现:
图中的 SpanContext 是一次申请中会共享的数据,因而叫做 Span 上下文,一个服务节点在上下文中放入的数据对于后续的所有节点都可见,因而能够用来做信息传递。
SOFATracer
TraceId 生成
TraceId 收集一次申请中的所有服务节点。其生成规定须要防止不同 TraceId 之间的抵触,并且开销不能很高,毕竟 Trace 链路的生成是业务逻辑之外的额定开销。SOFATracer 中的 TraceId 生成规定是:服务器 IP + 产生 ID 时候的工夫 + 自增序列 + 以后过程号,比方:
0ad1348f1403169275002100356696
前 8 位 0ad1348f 即产生 TraceId 的机器的 IP,这是一个十六进制的数字,每两位代表 IP 中的一段,咱们把这个数字,按每两位转成 10 进制即可失去常见的 IP 地址示意形式 10.209.52.143,大家也能够依据这个法则来查找到申请通过的第一个服务器。前面的 13 位 1403169275002 是产生 TraceId 的工夫。之后的 4 位 1003 是一个自增的序列,从 1000 涨到 9000,达到 9000 后回到 1000 再开始往上涨。最初的 5 位 56696 是以后的过程 ID,为了避免单机多过程呈现 TraceId 抵触的状况,所以在 TraceId 开端增加了以后的过程 ID。
伪代码如下:
TraceIdStr.append(ip).append(System.currentTimeMillis())
append(getNextId()).append(getPID());
SpanId 生成
SpanId 记录服务调用拓扑,在 SOFATracer 中:
- 点代表调用深度
- 数字代表调用程序
- SpanId 由客户端创立
SOFATracer 中 TraceId 和 SpanId 的生成规定参考了阿里的鹰眼组件
合并调用 Span 和被调 Span,联合 TraceId 和 SpanId 就能构建残缺的服务调用拓扑:
Trace 埋点
然而,咱们如何生成并获取到 Trace 数据呢?这就得 Trace 采集器(Instrumentation Framework)退场了,其负责:
- Trace 数据的生成、传递和上报
- Trace 上下文的解析和注入
并且 Trace 采集器还要做到主动、低侵入和低开销等。典型的 Trace 采集器构造如下,其在业务逻辑之前埋点:
- Server Received (SR), 创立一个新的父 Span 或者从上下文中提取
- 调用业务代码
- 业务代码再次发动近程服务调用
- Client Send (CS) 创立一个子 Span,传递 TraceId、SpanId 和透传数据
- Client Received (CR), 完结以后子 Span,记录 / 上报 Span
- Server Send (SS) 完结父 Span,记录 / 上报 Span
步骤 3-5 可能没有,也可能反复屡次。
埋点逻辑的实现多种多样,目前支流的有如下几种形式:
- Filter,申请过滤器 (dubbo, SOFARPC, Spring MVC)
- AOP 切面 (DataSource, Redis, MongoDB)
a.Proxy
b.ByteCode generating
- Hook 机制 (Spring Message, RocketMQ)
Java 语言中,SkyWalking 和 PinPoint 都应用 javaagent 形式做到主动、无侵入埋点。典型的,SOFATracer 实现 Spring MVC 的 Trace 埋点如下:
SOFATracer 的 Span 100% 创立,只是 log/report 反对采样,相对来说,log/report 的 overhead 更高,更容易在大流量 / 负载下成为性能瓶颈。而其余 Trace 零碎,Span 是采样生成的,但为了在调用出错的状况下能 100% 有 Trace,他们采纳了逆向采样的策略。
SOFATracer 默认把 Trace 信息打印到日志文件中
- client-digest:调用 Span
- server-digest:被调用 Span
- client-stat:一分钟内调用 Span 的数据聚合
- server-stat:一分钟内被调用 Span 的数据聚合
默认日志格局是 JSON,然而能够定制。
APM
一个典型的 Trace 零碎,除了 Trace 的采集上报之外,还会有收集器(Collector)、存储(Storage)和展现(API & UI):Application Performance Management,简称 APM,如下图所示:
图片起源:https://pinpoint-apm.github.io/pinpoint/overview.html
Trace 数据上报个别要求包含实时性、一致性等,SOFATracer 默认反对 Zipkin 上报;在存储之前波及到流式计算,调用 Span 和被调用 Span 的合并,个别采纳 Alibaba JStorm 或者 Apache Flink;在解决实现之后会放到 Apache HBase 中,因为 Trace 数据只是短时间有用,因而个别会采取过期数据主动淘汰机制,过期工夫个别是 7~10 天左右。最初的展现局部,从 HBase 中查问、剖析须要反对:
- 有向无环图的图形化展现
- 依照 TraceId 查问
- 依照调用者查问
- 依照被调用者查问
- 依照 IP 查问
图片起源:https://pinpoint-apm.github.io/pinpoint/images/ss_server-map.png
在蚂蚁团体外部,咱们没有采纳 Span 上报,而是 Span 打印到日志之后按需采集,其架构如下:
(其中 Relic 和 Antique 不是实在的零碎名。)
宿主机上有 DaemonSet Agent 用于采集 Trace 日志,digest 日志用于问题排查 & stat 日志用于业务监控,也就是要采集的日志内容。日志数据采集之后,会通过 Relic 零碎解决:单机日志数据清理、聚合;再之后通过 Antique 零碎的进一步的整合,通过 Spark 将 Trace 的服务数据做利用和服务纬度的聚合。最初,咱们将解决过后的 Trace 数据存到时序数据库 CeresDB 中,提供给 Web Console 查问和剖析。这个零碎还能够配置监控和报警,以便提前预警利用零碎的异样。目前以上监控和报警能够做到准实时,有 1 分钟左右的提早。
全链路追踪的倒退始终在不断完善,性能不断丰富,现阶段波及到的 Application Performance Management 不仅蕴含了全链路追踪的的残缺能力,还包含:
- 存储 & 剖析,丰盛的终端个性
- 全链路压测
- 性能分析
- 监控 & 报警:CPU、内存和 JVM 信息等
在蚂蚁团体外部,咱们有专门的压测平台,平台发动压测流量的时候,会自带人为结构的 TraceId、SpanId 和透传数据(压测标记),实现日志离开打印。欢送选用 SOFATracer 作为全链路追踪工具,SOFATracer 的疾速开始指南 Link:
瞻望
SOFATracer 的将来倒退布局如下,欢送大家参加奉献!我的项目 Github 链接。
相干链接
SOFATracer 疾速开始:https://www.sofastack.tech/projects/sofa-Tracer/component-access/
SOFATracer Github 我的项目:https://github.com/sofastack/sofa-Tracer
OpenTracing:https://opentracing.io/
OpenTelemetry:https://opentelemetry.io/
本周举荐浏览
- KCL:申明式的云原生配置策略语言
- 蚂蚁团体万级规模 k8s 集群 etcd 高可用建设之路
- 咱们做出了一个分布式注册核心
- 还在为多集群治理懊恼吗?OCM 来啦!
更多文章请扫码关注“金融级分布式架构”公众号