Back
Featured image of post 链路追踪方案选型及试用

链路追踪方案选型及试用

链路追踪

可观测性三剑客

  • Metrics
    相关服务在运行时被捕获的指标。一个监控指标事件包括指标本身、时间和关联的元数据。比如CPU使用率等。
  • Traces
    提供一个请求发往应用时所发生事情的全局视野。
  • Logs
    服务写入的结构或非结构化的文本记录,包括时间戳、元数据。在 OpenTelemetry 中,不属于分布式跟踪或指标的任何数据都是日志,通常缺少上下文。

链路追踪的技术演变

技术架构在近几年的不断发展下,逐渐趋向微服务、服务网格,甚至微函数的形态演变,这种功能拆分和单体缩小的架构模式带来维护成本降低,软件复用率提高等收益的同时,也导致了调用链路复杂,问题定位困难等问题,亟需新的技术方案来提高整体架构的可观测性。

最初,谷歌的一篇论文 «Dapper, a Large-Scale Distributed Systemds Tracing Infrastructure» 介绍了内部未开源的Dapper这个分布式链路追踪系统的设计理念和使用场景。随后,谷歌放出了开源版的OpenCensus。

Opentracing的诞生则试图为分布式追踪创建更多的标准化API及工具,逐渐被Zipkin、Jaeger、skywalking等支持,一时之间成为业界的标杆。

天下大势,分久必合。最终,CNCF孵化的OpenTelemetry合并了Opentracing和OpenCensus,实现了Metric、Tracing、Logging的统一及融合,成为业界的终极和唯一标准。

关键术语

  • Span
    表示工作/操作的基础单元,跟踪一个请求进行的特定操作,来描述该操作执行期间发生的情况。包括名称、时间相关的数据、结构化的日志、有关跟踪的操作的其他元数据(属性)。
  • Collector
    用于接收、处理和导出遥测数据的代理
  • Exporters
    为了可视化和分析遥测数据,需要将数据导出到收集器或后端,例如 Jaeger、Zipkin、Prometheus

选型

初步筛选了几个比较成熟的案例,比如Jaeger,Zipkin,Skywalking,Pinpoint。其中Pinpoint对性能影响最大,且支持的语言最少,基于业务场景的需求考虑最先排除掉。下面针对几个维度对几款产品进行比对

开源项目 开发团队 github仓库 star数量 前端UI支持 原生告警支持 prometheus监控 代码侵入 链路监控颗粒度 后端存储支持 采集端语言支持 特点 云原生部署
Jaeger Uber jaeger 17.7k 支持 无 支持 有 接口级 内存,Cassandra,kafka,ELK,ClickHouse Java Python NodeJs Go C++ UDP传输,性能好,但容易丢包 支持k8s
Zipkin twitter zipkin 16.2k 支持 无 支持 有 接口级 Cassandra, kafka, ELK, MySQL Java Go PHP JavaScript Python lua SpringCloud继承好,性能损耗大 无
SkyWalking 吴晟(前华为云) skywalking 21.9k 支持 支持 支持 基于ASM字节码增强技术,无代码侵入 代码方法级别,可追踪到中间件调用,比如Redis ELK,MySQL,PostgreSQL Java Lua Go PHP NodeJS 支持dubbo,SpringCloud, SpringBoot集成,依赖多,框架稍重,但性能损耗最小 支持k8s

考虑到代码侵入性和性能损耗问题,暂选择skywalking进行试用。

实践

无代码侵入的魔法

对于Skywalking和Pinpoint,我最感兴趣的是无代码侵入的实现。这是一种叫做字节码增强的技术,底层实现为ASM。

对于Java应用来说,ASM的实现有两种方式:Attach和Javaagent。其中Attach的实现逻辑如下:

  1. Attach JVM通过Attach API 获取目标JVM,底层通过socket通讯。
  2. Attach JVM指定目标JVM挂载agent.jar包,执行其中的agentmain方法,对目标JVM类的字节码进行修改。
  3. Attach JVM通过socket向目标JVM发送指令,目标JVM收到后进行响应,以此实现监控。

而Javaagent的方式更为直观,就是启动的时候加入javaagent参数,直接指定需要挂载的agent:

java -javaagent:/path/agent,jar=key1=value1,key2=value2 -jar myJar.jar
  1. 目标JVM通过javaagent参数启动, 执行agent的premain方法;
  2. agent中通过JVM暴露的接口添加一个Transformer,顾名思义它可以Transform字节码;
  3. 目标JVM在类加载的时候会触发JVM内置的事件,回调Transformer以实现字节码的增强。 Byte Buddy作为一款基于ASM的类库,兼顾高性能、易用、功能强大等特点。

skywalking上手

版本: v9.5.0
存储: PostgreSQL

架构如图,并没有调研时感觉的笨重

其中agent/探针作为采集器,通常采用gRPC协议进行数据通讯,性能比较理想。backend负责收集和存储数据。GraphQL是一个类似于PromQL的查询工具。

集成了几个java应用后,可以看到自动绘制的拓扑结构,观测效果如下。

除了链路监控外,skywalking还支持端点负载延迟和成功率监控等,对于性能分析也是一大利器!

问题汇总

  • 试用期间频繁OOM
    系默认存储h2的性能问题,线上需要更换方案,本次试用采用PostgreSQL。
  • 负载较重的应用性能影响较大
    适当降低采样率,有效缓解
  • grafana集成
    官方文档的grafana dataSource无效,疑似失去了维护。Native UI倒还可以
  • jetty托管的java应用传递javaagent参数失效
    官方文档提及的运行参数修改针对jetty.sh中JAVA_OPTIONS进行修改,而systemd托管的jetty配置了forking模式,无法传递参数。本次试用做法是在$JETTY_BASE目录下的start.ini中插入可选参数。 https://github.com/eclipse/jetty.project/issues/7754

参考文档

Built with Hugo
Theme Stack designed by Jimmy