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