2.4 链路跟踪系统
在大规模微服务系统中,服务之间的调用链路错综复杂。无论是数据统计、故障定位还是性能分析,都离不开辅助工具的支撑。常用的辅助工具如图 2-18 所示,它们是业务日志(Logging)、监控指标(Metrics)和链路跟踪(Tracing)。
图2-18 微服务架构下的常用辅助工具
● 业务日志:它工作在事件粒度上。业务日志记录了非常细致的事件和行为,因此它是用来进行问题排查的最精细的工具。由于日志量通常较为庞大,在工程实践中我们常常会利用诸如 ELK(Elasticsearch、Logstash、Kibana)等技术平台来进行日志的集成、检索和分析。
● 监控指标:它擅长对具有趋势性的、全局性的、宏观性的问题进行排查。正如上一节所探讨的,监控指标是自成体系的复杂系统,它包括指标计算、指标持久化和可视化以及告警系统等众多模块。
● 链路跟踪:无论是业务日志还是监控指标,都无法很好地对微服务之间的关联性问题进行高效排查,而这便是链路跟踪这个工具的用武之地。链路跟踪系统通过将请求链路上的所有事件和指标进行标记与聚合,从而为我们提供了进行关联检索和请求链路分析的能力。
2.4.1 应用场景与设计目标
由于链路跟踪系统可以较为完整地记录和复现请求链路上的所有关联事件与数据指标,因此它具有以下一些能力。
● 故障定位:链路跟踪系统可以清晰地绘制出指定请求的完整运行轨迹,它和业务日志形成了优势互补,因此我们可以结合两者来实现故障的快速定位,并对故障的源头和传播路径进行深入分析。
● 数据分析:链路跟踪系统可以将请求链路上的诸如性能、延迟和负载等精细的监控指标进行捕获与聚合,辅助使用者来进行用户数据和服务状态的分析工作。
● 依赖分析:链路跟踪系统可以将微服务之间的依赖关系进行可视化展示,有助于使用者对用户行为和服务关系进行理解。
除了需要满足上面这些功能性需求,优秀的分布式链路跟踪系统通常还需要具备以下一些特性。
● 低损耗:链路跟踪系统通常会带来一定的资源消耗和性能损耗,所以它会在一定程度上影响使用者对被观测服务的分析和判断。优秀的链路跟踪系统需要竭尽所能地利用诸如请求采样和运行时优化等手段来减小性能损耗。
● 低侵入:链路跟踪系统作为非业务组件,应当尽量减少代码层面的侵入性来方便业务方的使用。虽然完全的非侵入式集成往往是难以实现的,但是系统可以从减少侵入的层面来降低开发者的感知度。
● 可扩展:链路跟踪系统需要具备优秀的可扩展性设计来支持大规模部署,它也需要提供可扩展的操作平台来满足不同使用方的定制化需求。
2.4.2 系统架构
在链路跟踪系统中,诸如 Pinpoint、Zipkin 等常见的开源解决方案均借鉴了 Google Dapper 的设计思路和系统架构。Google Dapper 链路跟踪系统的核心思想是利用 Trace 和 Span 将请求链路上的事件与数据进行关联,图 2-19 展示了Google Dapper 的数据模型和用户使用界面。
● Trace:链路跟踪系统利用它来标识和记录一次完整的请求链路,并基于此来绘制调用拓扑图和完整的运行序列。TraceID 一般在前端系统等请求发起端生成并被注入后续链路调用的 RPC Header 中进行传播。
● Span:链路跟踪系统利用它来标识和记录请求链路中一次跨进程的通信事件及其附属信息,在图 2-19 所示的例子中,服务 A 对于服务 B 的请求调用就是一个 Span。由此可见,一次完整的请求链路是由多个相互衔接的 Span 组成的,它们通常形成了一个树状的调用拓扑图。
图2-19 Google Dapper 的数据模型和用户使用界面
在以 Trace 和 Span 为核心数据模型的基础上,链路跟踪系统的整体架构和运转流程可以用图 2-20 来表示,日志收集系统、日志处理系统和链路查询平台是最核心的三个组成部分。
图2-20 链路跟踪系统的整体架构和运转流程
● 日志收集系统:各个应用服务利用与语言相关的 SDK 将链路跟踪数据导入元数据消息队列和详细数据消息队列中,前者主要记录 TraceID、SpanID、用户标识和时间戳等核心关联信息,后者负责记录请求参数、响应结果、性能指标等与服务相关的详细数据。通过对这两部分数据的解耦,链路跟踪系统可以选择具有针对性的技术栈来有效地提高数据存储和数据处理的效率。
● 日志处理系统:对于存在于元数据消息队列和详细数据消息队列中的链路跟踪数据,系统可以按照不同的方式进行消费和处理。通常来说,元数据解析后会被存入 Elasticsearch 这类的检索服务中,而详细数据由于体量较大,则会被存储在HBase 这类的分布式列式存储系统中。
● 链路查询平台:它是最终交付给使用者进行链路跟踪数据查询和问题排查的可视化操作终端。当使用者在该平台上提交了服务名称和时间范围等关键检索信息后,平台利用 Elasticsearch 等检索服务来查找符合条件的 TraceID,然后利用 TraceID 并根据查询需求从分布式列式存储系统中拉取相应的详细数据,最后把这些数据汇总后在操作平台上进行可视化展示。