但是微做事架构也带来了新的问题:拆分后每个用户要求可能须要数十个子系统的相互调用才能终极返回结果,如果某个要求出错可能须要逐个子系统排查定位问题;或者某个要求耗时比较高,但是很难知道韶光耗在了哪个子系统中。全链路追踪系统便是为理解决微做事场景下的这些问题而出身的。一样平常地,该系统由几大部分组成:
客户端埋点 SDK :集成在各业务运用系统中,完成链路追踪、数据采集、数据上报等功能;实时数据处理系统 :对客户端采集上来的数据进行实时打算和干系处理,建立必要索引和存储等;用户交互系统 :供应用户交互界面,供开拓、测试、运维等用户终极利用链路追踪系统供应的各项功能;离线剖析系统 :对链路追踪数据进行离线剖析,供应诸多强大的链路统计剖析和问题创造功能;二、多措辞有赞目前的运用类型有很多种,已经支持追踪的措辞有 Java、Node.js、PHP。那么,如何让跨不同措辞的调用链路串到一起呢?有赞的链路追踪目前在利用的是 Cat 协议,业界也已经有比较成熟的开源协议:OpenTracing,OpenTracing 是一个“供应商中立”的开源协议,利用它供应的各措辞的 API 和标准数据模型,开拓职员可以方便的进行链路追踪,并能轻松打通不同措辞的链路。
Cat 协议与 OpenTracing 协议在追踪思路和 API 上是大同小异的。基本思路是 Trace 和 Span:Trace 标识链路信息、Span 标识链路中详细节点信息。一样平常在链路的入口运用中天生 traceId 和 spanId,在后续的各节点调用中,traceId 保持不变并全链路透传,各节点只产生自己的新的 spanId。这样,通过 traceId 唯一标识一条链路,spanId 标识链路中的详细节点的办法串起全体链路。一个大略的示意图如下:

实际每个节点上报的数据中还包含一些其他信息,比如:韶光戳、做事标识、父子节点的 id 等等。
三、客户端埋点 SDK3.1 Java Agent 与 Attach APIJava Agent 一样平常通过在运用启动参数中添加 -javaagent 参数添加 ClassFileTransformer 字节码转换器。JVM 在类加载时触发 JVMTI_EVENT_CLASS_FILE_LOAD_HOOK 事宜调用添加的字节码转换器完成字节码转换,该过程时序如下:
Java Agent 所利用的 Instrumentation 依赖 JVMTI 实现,当然也可以绕过 Instrumentation 直策应用 JVMTI 实现 Agent。JVMTI 与 JDI 组成了 Java 平台调试体系(JPDA)的紧张能力。
有赞的运用启动脚本都是由业务方各自掩护,因此要在成百上千的运用启动脚本中添加 -javaagent 参数是个不小的事情量。Java 从 Java 6 开始供应了 JVMAttachAPI ,可以在运行时动态 attach 到某个 JVM 进程上。 AttacheAPI 须要的进程 pid 参数,如果获取当提高程的 pid 是一个难点。不同的 JVM 版本有不同的办法,比较方便的是,字节码增强框架 Byte-Buddy 已经封装好了上述过程: JMX 或 java.lang.ProcessHandle 接口获取当提高程的 pid,只须要利用 ByteBuddyAgent.install() 就能 attach 到当提高程。
Byte-Buddy 是一个精良的字节码增强框架,基于 ASM 实现,供应了比较高等的 subClass()、redefine()、rebase() 接口,并抽象了强大丰富的 Class 和 Method 匹配 API。
3.2 透明升级有赞内部的框架和中间件组件已经进行统一托管,由专门的 Jar 原谅器卖力托管加载事情,险些所有 Java 运用都接入了该 Jar 原谅器,Jar 原谅器在运用的类加载之前启动。借助 Jar 原谅器供应的入口,链路追踪的 SDK 在运用启动之前完成字节码转换器的装载事情,同时 SDK 也托管在该 Jar 原谅器中,进而在实现运用无感知的追踪同时,又实现了全链路追踪 SDK 的透明升级。全体带起过程如下图所示:
运用无感知的自动化追踪与透明升级办法,大大提升了后续迭代的速率,运用接入本钱降到 0、追踪运用的比例靠近 100%,为后续发展带来了更多可能。与非透明办法的追踪比拟如下:
3.3 异步调用追踪
要求在一个进程内部可能会有多个子调用,Trace 信息在进程内部共享一样平常是通过 ThreadLocal 实现的,但是当有异步调用环境时,这部分调用可能就会在链路中丢失。我们须要做的是跨线程透传 Trace 信息,虽然 JDK 内置的 InheritableThreadLocal 支持父子线程通报,但是当面对线程池中线程复用的场景时还是不能知足需求。
比较常见的办理方案是 Capture/Replay 模型:在创建异步线程时将当前哨程高下文进行 Capture 快照,并通报到子线程中,在子线程运行时先通过 Replay 回放设置通报过来快照信息到当前高下文。详细流程如图:
由于内部有通用的线程工具类 FrameworkRunnable 和 FrameworkCallable ,因此只须要对这两个工具类进行统一增强就可以知足大部分异步调用的追踪场景。其余供应了异步处理工具 AsyncUtil ,在利用了自定义线程时,利用 AsyncUtil.wrap() 对自定义线程进行包装即可实现 Capture/Replay 的过程。
3.4 碰着的问题包冲突问题 :链路追踪 SDK 依赖的一些包可能会与业务系统的依赖发生版本冲突,比如 SDK 依赖的 Byte-Buddy 框架在很多运用中也有间接依赖,SDK 在利用过程中加载的 Jar 可能会与运用依赖的版本冲突。利用 maven 的 shade 插件可以有效的办理这个问题,shade 插件基于 ASM 实现,通过扫描 SDK Class 中的 import 引用进行包名更换,可以有效避免这个问题,详细的利用用法请参照 maven-shade-plugin 文档;API 耦合问题 :除了 Java Agent 透明追踪外,某些场景须要供应 API 给业务系统显式调用,而 API 要完成干系功能就必须与 SDK 的逻辑有交互,这样业务系统就必须通过 API 间接依赖 SDK。这时可以供应空的 API 实现,然后用 SDK 增强 API 实现原来的逻辑,将原来要依赖 SDK 才能实现的逻辑通过运行时字节码增强注入到 API 实现中。方便的解耦 API 与 SDK 依赖耦合问题;Child-first 类加载可能去世锁问题 :如果 Jar 原谅器没有遵照双亲委派模型,而链路追踪的 SDK 又是由 Jar 原谅器托管加载的,则可能由于字节码增强本身须要加载类并且类加载过程中的锁机制导致线程去世锁,这时须要在 ClassFileTransformer 中进行 Classloader 过滤;四、系统间集成4.1 与统一接入系统集成统一接入系统是有赞外部流量的接入代理系统。
由于链路有采样率设置,有时在测试或排查线上问题时未便利。为了支持链路 100% 采样,我们支持在前端页面要求的 HTTP Header 中设置类似 -XXDebug 参数,统一接入系统判断在 HTTP 要求头中包含特定的 -XXDebug 参数时,天生符合链路采样特色规则的 traceId 从而实现测试要求 100% 采样。
4.2 与日志系统集成为了使业务系统在上报日志给天网日志系统时自动记录 traceId,链路追踪 SDK 在开启追踪后会将 traceId put 到 MDC 中,天网日志 SDK 在记录日志时会获取 MDC 中的 traceId,并作为日志的描述数据一起上报,并进行索引。在日志查询时,支持按 traceId 查询。
同时天网日志系统对每次查询的结果数据页的日志 traceId 进行批量打算,判断哪些日志记录对应的要求在链路追踪系统中被采样,对采样过的日志记录的 traceId 更换成超链接,支持一键跳转到对应的链路详情页。
五、数据处理架构链路数据处理利用 Spark Streaming 任务准实时打算,处理过的数据进行 ES 索引,并存储在 Hbase 中。数据上报过程利用常见确当地数据上报 agent + remote collector 的办法,然后汇到 kafka 行列步队供实时任务处理,架构视图如下所示:
本地 agent 之以是采取本地 agent 与远程 collector 办法,一方面考虑到大流量数据上报时的网络拥塞,利用本地 agent,SDK 可以将数据发送给 agent 由 agent 异步发送出去,减轻了 SDK 中数据上报行列步队溢出的风险;另一方面,如果数据直接从运用端连接到 kafka 行列步队,整体架构虽然变大略了,但是 kafka 所能承受的连接数比较有限,随着运用数的增长,整体架构会变得无法扩容。链路优化 数据上报的链路经历了多次迭代优化,由于不同措辞客户端上报数据的格式问题,旧版本的链路很长,多了几步数据格式转换与转发的过程。随着链路的优化迭代,每减少一个转发与转换的环节对付有赞的数据量都能节省许多资源。数据处理优化 数据处理部分旧版本利用的是 Java 任务,改成 Spark Streaming 处理数据后整体打算资源的花费也节省了原来的一半,包括 CPU 核数与内存总量。六、总结与展望
全链路追踪系统包含几大部分:链路采集 SDK、数据处理做事、用户产品。SDK 部分比较偏技能。数据处理更磨练数据处理的吞吐能力和存储的容量,采取更高等的链路采样办理方案可以有效降落这部分的本钱。用户产品紧张磨练的是设计者对用户需求的把握,全链路追踪可以做很多事情,产品上可以堆叠出很多功能,若何能让用户快速上手,简洁而又易用是链路追踪产品设计的一大寻衅。未来一段韶光,有赞全链路追踪会环绕以下几个方面连续演进:
赋能有赞云 :给有赞云开拓者用户供应有容器运用的链路追踪能力;开源协议支持 :数据模型与链路追踪 API 迁移到 OpenTracing 协议上,支持更多新措辞的快速追踪;用户产品迭代 :持续提升产品体验,供应更相符用户利用场景的产品;支持更多组件 :支持更多组件和中间件的追踪能力;离线剖析能力 :基于链路追踪的数据,挖掘离线剖析能力,供应更丰富和强大的功能;原文链接:https://www.tuicool.com/articles/Y3y6VnN
每天都会有更新看过的朋友可以关注一波,Java学习路线和优质资源评论或后台回答“java”获取