gitbook/全链路压测实战30讲/docs/441338.md
2022-09-03 22:05:03 +08:00

14 KiB
Raw Permalink Blame History

11 | 链路追踪:如何选择一款适合自己项目的工具?

你好,我是高楼。

从这里开始,我们进入链路追踪改造部分,这节课,我们来看一下怎么在全链路压测项目中选择合适的链路追踪方案。

为什么需要链路追踪?

首先,我们看下这个课程的开源电商项目的部署架构。

图片

从部署架构图中你可以很直观地看到在微服务架构下系统的功能是由大量的微服务协调组成的。例如电商下单业务就需要会员系统服务mall-member、认证中心服务mall-auth、订单系统服务mall-order、购物车系统服务mall-cart逐级调用才能完成。而实际在电商企业每个服务可能是由不同的团队进行开发部署在成百上千台服务器上的。

这么复杂的调用链路就带来一系列问题:

  1. 如何快速发现性能问题?
  2. 如何精准判断故障影响范围?
  3. 如何梳理服务依赖以及依赖的合理性?
  4. 如何分析链路性能问题以及容量规划?

当系统发生故障的时候,我们需要一种机制对故障点进行快速定位,确认到底是哪个服务、哪个接口出了问题,那么分布式链路追踪技术由此产生。

所谓的分布式链路追踪就是运行时通过某种方式记录下各服务之间的调用过程再通过可视化UI方式帮助相关人员快速定位到故障点。 现如今,分布式链路追踪已经成为微服务架构性能监控的底层基础设施,没有它,性能分析人员就像盲人摸象,根本无法彻底了解服务间链路通信的全过程。

而在我的RESAR 性能分析七步法中,分析架构图、拆分响应时间、定向分析都需要借助链路追踪来梳理服务依赖,分析业务核心链路也要用到它。可想而知,链路追踪对性能项目的作用有多大。

图片

链路追踪的设计需求

知道了链路追踪的重要性,那么,链路追踪应该做成什么样子呢?

总的来说,我们希望链路追踪能够从全局监控定向监控,从整体维度局部维度展示各项指标,将跨服务的所有调用链性能信息集中展现出来。这些信息有利于我们度量整体和局部性能,方便我们找到问题产生的源头,极大缩短性能分析时间。

首先我们需要关注在请求处理期间各个调用的各项性能指标比如TPS、响应时间及错误数等。

  1. TPS收集链路拓扑可计算相应组件、服务的实时数据
  2. 响应时间,整体调用和各个服务的响应时间等;
  3. 错误数,统计单位时间服务异常次数。

我们希望从链路追踪中就可以清晰地看到一个请求对应的每一段的耗时。比如说一个接口调用另一个接口、Redis、MySQL 等组件时的耗时。当我们发现哪一段耗时比较长的时候,就可以到耗时长的那个组件上,根据定向监控的数据接着往下分析了。

另外,我们对全链路压测标识透传也是有要求的,那就是:

对于跨服务的调用,我们需要对所有涉及到的服务进行一一改造。添加压测标识的属性,以此保证传输中始终带着压测标识。

也就是说,这个压测标记需要在链路追踪中被识别、记录、并传递,这样我们就能做到区分请求(正常流量 & 压测流量)了。

好了,我们先来总结一下,我们希望通过链路追踪达到的目标:

  1. 请求链路追踪,快速定位问题:可以通过调用链结合业务日志快速定位错误信息;
  2. 可视化UI 细化服务各个阶段耗时并可视化展示,方便进行性能分析;
  3. 依赖优化:统计各个调用组件的可用性、梳理服务依赖关系,可做到精准优化;
  4. 数据分析,优化链路:可以得到流量的请求路径,汇总分析各业务场景;
  5. 区分流量:可以识别、记录、传递压测标记,做到快速区分请求(正常流量 & 压测流量)。

链路追踪的选型

上面我们介绍了链路追踪需要达到的几个主要目标,那么我们又该怎样选择适合自己项目的链路追踪组件呢?

Google Dapper 中已经提到了需要关注的几个主要的方面:

  1. 探针的性能消耗:对服务的影响要尽可能小,服务埋点本身会带来一定的性能损耗,这对于性能敏感的应用是致命伤;
  2. 代码的侵入性:对应用尽量少侵入,对业务尽可能透明;
  3. 可扩展性:支持集群部署,支持的组件越多越好;
  4. 数据的分析:数据分析要快,分析的维度要多。

目前业务主流的链路追踪系统,大致功能可以分为以下四大模块:

  1. 埋点与生成日志:可分为客户端、服务端、以及客户端和服务端双向埋点;
  2. 搜集与存储日志:分布式日志采集,一般都支持消息队列作为缓存,支持常见的 ElasticSearch 数据储存;
  3. 分析与统计调用链数据:调用链数据汇总,还原调用链路,并分析最终的调用形态;
  4. 可视化 UI 展示:直观地了解业务处理过程中服务间的依赖关系与处理时间、处理状态等信息。

目前业界流行的链路追踪组件有 Jaeger、Zipkin、SkyWalking 和 Pinpoint 等。但是,这些组件对业务代码的侵入性和不同系统的兼容性都各有其特点。

为了让你有个更为直观的认识,我给你画了个表格,我们一起来看看不同组件的优劣。

图片

从这张对比表可以看出:

  1. ZipkinJaeger 在各个方面的指标都差不多Jaeger 是 Zipkin Plus改良版
  2. 相对其它三种组件,Skywalking 的功能较为齐全,性能损耗也较低,同时客户端也支持多种主流语言;
  3. Pinpoint 是一个完整的性能监控解决方案,有从探针、收集器、存储到 Web 可视化界面等全套体系,但它在性能和可扩展性方面有所不足;
  4. 四种组件都支持 OpenTracing,这样开发者可以无缝切换追踪组件,使得通用链路追踪的实现成为可能。

总之,每种组件都有它的优缺点,我建议你在选择链路追踪组件的时候,一定要根据自身项目的实际情况,仔细考量哪些地方可以妥协,哪些地方可以放弃,最终选择出一款最适合自己项目的组件。

考虑到我们的电商项目是 Spring Cloud 技术栈,在压测标记跨服务透传上又存在刚性需求,而 Spring Cloud Sleuth 是一套原生的解决方案。

Sleuth 是 Spring Cloud 提供的服务治理模块,在其标准生态下内置了 Sleuth 这个组件。它通过扩展 Logging 日志的方式实现微服务的链路追踪。

利用 Sleuth 服务间原生传递上下文特性,在原有传输上下文的基础上,添加了压测标记的属性,以保证后续跨服务传输中始终带着压测标记。这样也就免去了代码的硬耦合。

Sleuth + Zipkin 是一套成熟的链路追踪解决方案,基于经典 X-B3 Trace 协议 的 Java 接口实现 Brave使用 Brave SDK提供了基本的操作 API手动埋点生成 Trace如果需要与框架或者项目集成的话就需要手动添加配置文件或增加代码它的 instrumentation 子项目,已经提供了 SpringMVC、MySQL、Dubbo 等等的常用组件链路追踪的功能。但是 SDK 埋点的方式,对业务代码存在侵入性,当升级埋点时,必须要做代码的变更。

而性能更好的 Skywalking依赖 Java Agent 探针,通过字节码注入的方式修改目标方法的字节码,实现调用拦截和数据收集,可以做到真正的无侵入的埋点,在应用程序启动时使用 -javaagent 参数,就可以将探针包注入目标应用程序,完成埋点的植入。对业务代码无侵入的方式,可以做到无感的热升级。用户不需要理解深层的原理,就可以使用完整的监控服务。

但是,从改造难度和成本方面来说,**Brave 比字节码注入更容易上手,**简单阅读 Skywalking 和 Brave 插件的代码你就可以发现两者的实现难度有天壤之别。Brave 的代码量很少,核心功能都集中在 brave-core 这个模块下,一个中等水平的开发人员,可以在一天之内读懂它的内容,并且能对 API 的结构有非常清晰的认识。

作为一个专栏项目,我们希望能够尽量能覆盖绝大部分人群,所以最终我们选择了 Sleuth + Zipkin作为链路追踪解决方案

如果你对 Zipkin 还不是很了解的话,可以参考这篇文章《 快速了解分布式链路追踪系统 Zipkin 》,文中对 Zipkin 的入门知识做了详细的介绍。

链路追踪的改造

说完了链路追踪组件选型,紧接着我们看看如何让它在我们的电商项目中落地?

首先,我们来看一下电商项目集成 Sleuth+ Zipkin 的应用架构。

图片

从架构图中可以看到:我们构建了一个服务网关,通过 API 网关调用具体的微服务,所有的服务都注册到 Nacos 上;当客户端的请求到来之时,网关作为服务端的门户,会根据配置的规则,从 Nacos 中获取对应服务的信息,并将请求反向代理到指定的服务实例。

系统涉及的需要新增/改造业务服务与组件包含以下 10 个:

  1. Zipkin链路追踪系统
  2. Kafka消息队列
  3. ElasticSearch搜索引擎
  4. mall-gatewayAPI 网关
  5. mall-auth认证中心服务
  6. mall-member会员系统服务
  7. mall-order订单系统服务
  8. mall-cart购物车系统服务
  9. mall-protal商城后台系统服务
  10. mall-admin后台管理系统服务

顺便提下Zipkin 包括如下的 Transport 方式:

  1. HTTP通过 okhttp3urlconnection 实现。
  2. ActiveMQ通过 activemq-client 实现。
  3. RabbitMQ通过 amqp-client 实现。
  4. Kafka通过 kafkakafka08 实现。
  5. Thrift通过 libthrift 实现。

请求量级小的时候,选择 HTTP 方式即可。量级比较大的时候,我们推荐使用 Kafka 消息队列。

而 Zipkin Server Storage 负责存储链路数据,目前支持 Memory、MySQL、Cassandra、ElasticSearch 等数据库,不同数据库的适用环境也不一样:

  1. Memory默认存储器。主要用于简单演示生产环境下不推荐。
  2. MySQL小规模使用时可以考虑用 MySQL。
  3. ElasticSearch主流数据库。通常情况下都会采用 ElasticSearch 存储链路数据。
  4. Cassandra在 Twitter 内部被大规模使用,因为 Cassandra 易跨站,支持灵活的 schema。

我们这里将链路日志推送到 Kafka然后启动 Zipkin Server 聚合日志,监听 Kafka ,如果有新的消息则进行拉取存入到 ElasticSeach最后再用 Zipkin UI 展示链路过程。

最后,我们再来梳理下整个系统链路追踪改造部分,它大概分为五大部分:

  1. 在服务中加入 Spring Cloud Sleuth 生成链路追踪日志;
  2. 使用 Brave 库,集成 Zipkin 客户端埋点。使用 instrumentation 插件,实现对 SpringMVC、MySQL 等组件实现链路追踪的功能;
  3. 将链路日志推送到 Kafka
  4. 启动 Zipkin Server 聚合日志,监听 Kafka ,如果有新的消息则进行拉取存入到 ElasticSeach
  5. 最后使用 Zipkin UI 展示链路过程、使用 Kibana 查询链路数据。

完成这些内容后,整体展示出来的内容如下图所示:

图片

总结

好了,这节课我们讲到这里,我来总结一下:

  • 现如今链路追踪是微服务架构的基础设施,也是性能分析人员不可缺少的“神兵利器”;
  • 链路追踪、快速定位问题、可视化UI、数据分析等功能已成为众多链路追踪工具的标配
  • 探针性能损耗低、对应用透明、可扩展性强,数据分析快且丰富等功能是用户重点关注的内容;
  • 另外我们还一起梳理了全链路压测中链路追踪的需求、目标和几种常见的组件,确定了系统最后的选型方案。

总之,每种组件都有它的优缺点,在做链路追踪组件的选型时,一定要根据自身项目的实际情况,仔细衡量哪些地方可以妥协,哪些地方可以放弃,从而选择一款适合自己项目的组件。

下一节课,我们将进入实践环节,我会通过案例演示如何应用 Sleuth+Zipkin 来实现链路追踪改造。

思考题

在课程的最后,我还是照例给你留两道思考题:

  1. 你知道链路追踪和系统监控的区别是什么?
  2. 除了我列出的链路追踪组件,你还知道哪些?

欢迎你在留言区和我交流讨论,我们下节课见!