炎炎夏日,当你打开外卖 APP 购买奶茶却发现下单失败;五一佳节,当你自驾游途中发现导航响应缓慢,频繁错过路口;深更半夜,当你辅导孩子功课,却发现 GPT 应用迟迟无法应答。不知你有没有想过,这些程序运行的背后到底是怎样的世界,每一次点击,每一次交互,又到底发生了什么?
如果你是一名 SRE,是否会关注系统的性能瓶颈在哪里?如果你是一名 AppOps,是否关注应用的健康度保持在安全的水位?如果你是一名业务运营,是否关注影响客户行为的关键路径和原因?
上述谜题的答案就是链路追踪,通过记录请求在系统中的流转路径与状态,可以真实还原每一次请求的调用轨迹,快速定位错慢根因,并且通过请求粒度的数据关联实现业务影响面分析、业务异常排查等诉求。
链路追踪的价值就在于“关联”,用户终端、网关、后端应用、依赖组件(如数据库、消息、大模型)等共同构成了链路追踪的轨迹拓扑大图。这张拓扑覆盖的范围越广,链路追踪能够发挥的价值就越大。而端到端链路追踪就是覆盖全部关联 IT 系统,能够完整记录用户行为在系统间调用路径与状态的最佳实践方案。
1. 端到端链路追踪的“三大难题”
不同开发语言、链路框架的实现不尽相同,真正实现端到端链路追踪,需要解决三个难题:链路插桩、链路采集与加工、链路上下文透传。
- 链路插桩,顾名思义就是在关键方法执行前后添加链路追踪的埋点代码,从而记录相应的方法名称、耗时、状态等信息。链路插桩是一切的基础,只有已插桩方法才会生成 Trace 链路数据,可以被追溯和观测。但是链路插桩的难点是哪些方法需要插桩?如何低成本的新增或管理插桩逻辑?如何保障链路插桩的准确、性能和稳定?
- 链路采集与加工,就是把已经生成的链路数据收集到指定的后端进行处理与存储,以便后续进行分析。链路采集的难点在于如何确定采集目标并收到完整的链路数据,特别是云产品服务(如网关)生成的链路数据。链路加工的难点在于如何处理非原生 Trace 数据转义(如网关访问日志),或者多源异构链路模型的归一化。
- 链路上下文透传,是最容易被忽视,也是最难处理的问题。目前业界链路透传协议尚未完全统一,常用的主流协议包括 w3c、b3、jaeger 和 skywalking。不同系统之间由于开发语言、开源框架、产品归属等原因最终选择的链路协议不一致是比较普遍的,从而导致调用链断链不全等问题。另外,在迁移链路框架的过程中,也会出现协议不兼容的情况,比如 Skywalking 与 OpenTelemetry。
2. 阿里云端到端链路追踪解决方案
阿里云 ARMS(含可观测链路 OpenTelemetry 版)目前已经支持用户终端(Web/Andriod/iOS)-> 云网关(ALB/MSE/Ingress/ASM/ApiGateway)-> 后端应用(Java、Go、Python 等)-> 云组件(数据库、消息、大模型等)的端到端全链路打通,如下图所示。
2.1 链路插桩:Java/Go 等主流语言推荐 ARMS 自研探针,兼容开源提升多语言覆盖度
针对 Java/Go/Python 等主流语言,推荐接入 ARMS 自研探针提升链路插桩的质量、性能、稳定性和易用性。同时,为了更广泛的支持其他语言,可观测链路 OpenTelemetry 版全面兼容 OpenTelemetry、SkyWalking、Zipkin、Jaeger 4 种主流链路框架 10+ 种多语言的链路插桩与数据上报,如下表所示。
ARMS 与可观测链路 OpenTelemetry 数据完全互通,在多语言场景建议结合使用。
编程语言 | ARMS 应用监控(自研探针,SLA 有保障) | 可观测链路 OpenTelemetry 版(开源客户端,自行管理) | 推荐接入方式 |
Java | 自动埋点 | 自动埋点 | ARMS |
Go | 自动埋点开发中,7月发布 | 自动埋点 | SkyWalking -> ARMS |
Python | 自动埋点开发中,7月发布 | 自动埋点 | OpenTelemetry -> ARMS |
Node.js | 不支持 | 自动埋点 | OpenTelemetry |
.NET | 不支持 | 自动埋点 | OpenTelemetry |
PHP | 不支持 | 自动埋点 | OpenTelemetry |
Erlang | 不支持 | 自动埋点 | OpenTelemetry |
C++ | 不支持 | 手动埋点 | OpenTelemetry |
Swift | 不支持 | 手动埋点 | OpenTelemetry |
Ruby | 不支持 | 手动埋点 | OpenTelemetry |
Rust | 不支持 | 手动埋点 | SkyWalking |
ARMS 今年刚刚发布了 JavaAgent 4.0,全面拥抱 OpenTelemetry 生态,探针底座基于 OpenTelemetry 框架进行了全新升级,并额外提供多种资源监控、性能诊断、应用安全等数据。除了更丰富的数据,ARMS JavaAgent 4.0 还支持更加灵活的调用链采样策略、白屏化探针管理、全方位自监控、动态功能降级等高阶特性,更加适合企业级客户的生产环境应用,如下表所示。
能力类别 | 能力项 | ARMS 应用监控 | 开源 OpenTelemetry | 开源 SkyWalking |
接入方式 | 黑屏启动参数挂载 | 支持 | 支持 | 支持 |
白屏化自动挂载 | 支持K8S 环境:仅修改两行配置ECS 环境:页面勾选安装 | 不支持 | 不支持 | |
调用链 | 多协议透传与兼容 | w3c、jaeger、b3、skywalking、eagleeye | w3c、jaeger、b3 | skywalking |
采样策略 | 固定比例采样、流量自适应采样、错慢异常采样、接口级自定义全采 | 固定比例采样[1] | 流量自适应采样[2] | |
Span 压缩 | 循环调用压缩,解决数据重复、查询慢问题 | 不支持 | 不支持 | |
日志 | 关联调用链(MDC) | 支持 | 支持 | 支持 |
指标 | 流量无损统计(不受采样率影响) | 支持 | 支持 | 不支持 |
监控指标 | 支持 RED、JVM、线程池、连接池、主机等指标 | 支持 RED、JVM 等部分指标 | 支持 JVM、连接池等部分指标 | |
维度下钻 | 支持接口上下游、异常等多维度下钻 | 不支持 | 不支持 | |
剖析 | 持续剖析 | 支持低开销、常态化运行(CPU +5%、Mem +0.2%)支持与调用链关联,慢调用下钻至方法栈 | 不支持 | 不支持 |
内存诊断 | 支持 HeapDump、火焰图 | 不支持 | 不支持 | |
在线诊断 | 支持 Arthas 实时诊断 | 不支持 | 不支持 | |
安全 | RASP 应用安全 | 支持 | 不支持 | 不支持 |
探针性能(数据来源于内部测试环境) | 启动时间 | 8.1s(优化中) | 6.2s | 8.7s |
资源开销 | CPU、RSS 基本持平(ARMS 额外支持更多功能,关闭后性能更优) |
2.2 链路采集与加工:深度集成阿里云生态,云产品链路一键接入
企业上云的一个痛点问题就是重度依赖云产品服务可用性,端到端链路追踪可以快速定位错慢请求异常节点,提升故障快恢效率,降低业务损失。那么如何接入云产品的调用链路数据呢?
可观测链路 OpenTelemetry 版与阿里云近 10 款云产品深度合作,完成了云产品内部链路插桩与数据上报。对于企业用户来说,只需在相应的云产品控制台一键启用链路追踪开关,就可以直接看到相应的调用链,大幅简化了链路采集成本,ALB 网关、MSE 网关以及 ARMS 用户体验监控的链路追踪接入效果如下图所示 。
受限于产品特性,不同云产品的链路插桩方案有所区别,配套的链路数据采集大致分为两类:
- Trace 直接/转发上报:以用户体验监控为例,内部实现链路插桩与 Exporter 直连上报,埋点更精细更灵活。
- 日志数据转 Trace:以 ALB 网关为例,后台消费访问日志,再转义成 Trace 数据,侵入性更小。
两种方案各有优劣,通常推荐 Trace 直连/转发上报,此种方案更规范。但是在性能要求高或者旧系统改造困难场景下,可以考虑日志转 Trace(前提条件是在日志中添加 TraceId 等链路上下文)。
目前,已经支持接入链路追踪的云产品、协议及接入指南如下表所示。
接入类别 | 接入端 | 接入指南 | 支持协议 |
用户终端 | Web/H5/小程序 | 用户体验监控关联 Trace[3] | w3c、b3、jaeger、skywalking、eagleeye |
Andriod | 通过 OpenTelemetry 上报 Android 应用数据[4] | w3c、b3、jaeger | |
iOS | 通过 OpenTelemetry 上报 Swift 应用数据[5] | w3c、b3、jaeger | |
网关 | ALB | 通过 ALB 链路追踪实现业务全链路分析[6] | b3 |
MSE | 开启网关链路追踪[7] | w3c、b3、skywalking | |
API Gateway | 配置 Trace 链路追踪[8] | b3 | |
ASM | 在 ASM 中实现分布式跟踪[9] | b3 | |
ACK Ingress | 使用 Ingress-tracing 实现链路追踪[10] | w3c、b3、jaeger | |
后端应用 | Java(自研) | 接入 ARMS 开始监控 Java 应用[11] | w3c、b3、jaeger、skywalking、eagleeye |
多语言(开源) | 接入可观测链路 OpenTelemetry 版[12] | w3c、b3、jaeger、skywalking | |
依赖组件 | 100+ 插件支持,覆盖 RPC、消息队列、数据库、任务调度等各种类型 |
2.3 链路上下文透传:统一阿里云端到端链路协议,自研探针兼容多协议转换
从单个应用组件的视角,完成链路插桩和数据采集,能在控制台上看到对应的 Trace 数据就已经大功告成啦。但是真正的端到端链路追踪必须将上下游的 Trace 以统一的协议进行串联,保证不断链,既有技术层面的挑战,也有协同层面的困难。
目前阿里云可观测已经基于 OpenTelemetry W3C 协议实现端到端链路打通,后续将逐步覆盖更多协议、更多组件的全链路透传,构建更完整、更灵活的链路生态,完整端到端调用链如下图所示。
相比于新应用接入 Trace,存量应用要实现端到端协议栈统一的挑战会更大。特别是面临新旧技术栈切换场景(比如 SkyWalking 迁移至 OpenTelemetry),既要保证存量运维体系持续可用,又要验证新体系的有效性,如何兼容两种不同链路体系共存?是影响存量应用技术栈升级或链路打通的最大难题。
为了解决这个问题,ARMS 自研探针做了大量的兼容性优化,最终实现了双探针共存,保证两套体系能够同时正确、稳定运行,直至迁移完成,如下图所示。
ARMS 自研探针支持多协议识别与透传,在某些特殊场景,如果上下游系统难以变更,可以通过 ARMS Agent 进行协议中转,比如上游 A 应用使用 Jaeger 协议 -> ARMS Agent(接收 Jaeger,向下透传 Jaeger + Zipkin B3) -> 下游 B 应用使用 Zipkin B3 协议,最终实现 TraceId 的透传与打通。
3. 后续规划:倡导链路追踪行为公约,促进链路生态繁荣生长
链路追踪行为公约:链路插桩、采集和协议透传只是端到端链路追踪的基础,如何更加有效的使用链路数据解决稳定性运维、业务运营增长等方面的诉求,还需要更多的探索,比如统一的链路行为控制(采样策略、流量标签等)、广泛的数据关联分析(Trace 关联指标、日志、事件等)。
OpenTelemetry 最佳实践:OpenTelemetry 作为可观测的主流开源标准,提供了丰富的链路插桩组件支持。但是,许多企业开发者在将其应用于生产环境时,普遍反馈缺乏最佳实践指导,比如如何实现异步场景链路上下文透传、过滤指定的 Span、关联应用日志、指定透传 Header 格式、将 TraceId 写入 HTTP Response Header 等。阿里云可观测团队秉持着“开源、开放”的精神,致力于提供全面、可靠的 OpenTelemetry 最佳实践指南(代码、文档、视频等),欢迎大家一起参与共建链接。
促进链路生态发展:链路追踪实现了跨节点的请求粒度数据透传与关联,基于链路体系能够孵化出丰富的链路生态,比如全链路压测、全链路灰度、架构感知、根因定位与影响面分析等。在 LLM 大模型领域,链路追踪也能发挥巨大的价值,帮助算法工程师或运维人员定位每一次模型训练或推理的过程与结果,有效识别并解决“幻觉”、评估调优等问题,阿里云 LLM Trace 将在 2024 年 5 月正式发布上线,效果如下图所示。
相关链接:
[1] 固定比例采样
[2] 流量自适应采样
[3] 用户体验监控关联 Trace
[4] 通过 OpenTelemetry 上报 Android 应用数据
[5] 通过 OpenTelemetry 上报 Swift 应用数据
[7] 开启网关链路追踪
[8] 配置 Trace 链路追踪
[9] 在 ASM 中实现分布式跟踪
[10] 使用 Ingress-tracing 实现链路追踪
[11] 接入 ARMS 开始监控 Java 应用
作者:涯海