背景
链路追踪是微服务中排查的利器,用一个 TraceId 就可以串起整个调用链路的所有环节,对排查一些生产问题帮助很大。但是目前公司自研的链路追踪系统因为资源限制,数据处理延迟很严重。本篇文章分享实习期间对链路追踪进行优化的过程。
实现原理
我们先简单的认识下一个典型的链路追踪系统:
如下图所示,如果想知道一个请求在哪个环节出现了问题,就要知道这个请求调用了哪些服务,调用的顺序和层级关系。这些调用信息像链条一样环环相扣,我们称之为调用链。
p1.png
而在这条链中,每个调用点,比如服务A对服务B的调用,服务B访问数据库,我们称之为 Span。将一次请求看作一个 Trace,使用唯一的 TraceId 标识,通过 SpanId 和 ParentId 记录调用顺序和层级关系,使用 Timestamp 记录调用的各项时间指标。
把 TraceId 相同的 Span 都整合起来,就可以绘制出这个 Trace 的调用情况图,帮助分析问题。如下图所示:
p2.png
存储系统架构
Trace 的数据有以下特点:
-
Trace 的 Span 数量各不相同:有的 Trace 只有一个 Span,有的 Trace 有上百个 Span。
-
数据量大:我们每天需要收集 8千万+ Span,这些 Span 组成 1千万+ Trace。
借鉴 Google 的 Dapper,我们选择 HBase 来存储 Trace 数据,它支持超大规模数据存储和稀疏存储动态列的特性可以满足存储 Trace 的需求,存储格式如下:
p3.png
p4.png
为了避免海量的 Trace 数据对 HBase 的冲击,我们使用 Kafka 在中间缓冲。Consumer 节点从 Kafka 拉取到 Span 后,以 TraceId 作为 RowKey,SpanId 作为 ColumnKey 存到 HBase 中。
问题
这种方式受限于 HBase 的写入速度(公司的的 HBase Trace 集