关于云原生:得物云原生全链路追踪Trace20架构实践

7次阅读

共计 5798 个字符,预计需要花费 15 分钟才能阅读完成。

导读:

分布式链路追踪作为解决分布式应用可观测问题的重要技术,得物全链路追踪 (简称 Trace2.0) 基于 OpenTelemetry 提供的可观测规范计划实现新一代的一站式全链路观测诊断平台,并通过全量采集 Trace 帮忙业务进步故障诊断、性能优化、架构治理的效率。

全量采集 Trace 数据 (日增数百 TB、数千亿条 Span 数据) 并以较低的老本保证数据的实时处理与高效查问,对 Trace2.0 后端整体的可观测性解决方案提出了极高的要求。本文将具体介绍 Trace2.0 背地的架构设计、尾部采样和冷热存储计划,以及咱们是如何通过自建存储实现进一步的降本增效(存储老本降落 66%)。

1. 整体架构设计

全链路追踪 Trace2.0 从数据接入侧、计算、存储到查问整体模块架构如上图所示。这里说一下各组件的外围能力:

  • 客户端 & 数据采集:集成并定制 OpenTelemetry 提供的多语言 SDK(Agent),生成对立格局的可观测数据。
  • 管制立体 Control Plane:对立的配置核心向数据采集侧下发各类动静配置发并实时失效;反对向各采集器下发动静配置并实时失效,反对利用按实例数灰度接入,并提供出入参收集动静开关、性能分析动静开关、流量染色动静配置、客户端版本治理等。
  • 数据收集服务 OTel Server:数据收集器 OTel Server 兼容 OpenTelemetry Protocol(OTLP)协定,提供 gRPC 和 HTTP 两种形式接管采集器发送的可观测数据。
  • 剖析计算 & 存储 OTel Storage:计算侧除了根底的实时检索能力外,还提供了场景化的数据分析计算次要包含:

    • 存储 Trace 数据:数据分为两段,一段是索引字段,包含 TraceID、ServiceName、SpanName、StatusCode、Duration 和起止工夫等根本信息,用于高级检索;另一段是明细数据(源数据,蕴含所有的 Span 数据)
    • 计算 SpanMetrics 数据:聚合计算 Service、SpanName、Host、StatusCode、Env、Region 等维度的执行总次数、总耗时、最大耗时、最小耗时、分位线等数据;
    • 业务单号关联 Trace:电商场景下局部研发多以订单号、履约单号、汇金单号作为排障的输出,因而和业务研发约定非凡埋点规定后 – 在 Span 的 Tag 里增加一个非凡字段 ”bizOrderId={理论单号}”– 便将这个 Tag 作为 ClickHouse 的索引字段;从而实现业务链路到全链路 Trace 造成一个残缺的排障链路;
    • Redis 热点数据统计:在客户端侧扩大调用 Redis 时入参和出参 SpanTag 埋点,以便统 Redis 命中率、大 Key、高频写、慢调用等指标数据;
    • MySQL 热点数据统计:依照 SQL 指纹统计调用次数、慢 SQL 次数以及关联的接口名。

    2. 尾部采样 & 冷热存储

    得物晚期的全链路追踪计划出于对存储老本的思考,在客户端设置了 1% 的采样率,导致研发排查问题时常常查问不到想看的 Trace 链路。那么 Trace2.0 为了解决这个问题,就不能仅仅只是简略地将客户端的采样率调整为 100%,而是须要在客户端全量采集 Trace 数据的同时,正当地管制 Trace 存储老本。且从实践经验来看,Trace 数据的价值散布是不平均的,随着工夫的推移 Trace 的数据价值是急速升高的。

全量存储 Trace 数据不仅会造成微小的老本节约,还会显著地影响整条数据处理链路的性能以及稳定性。所以,如果咱们可能只保留那些有价值、大概率会被用户理论查问的 Trace,就能获得老本与收益的均衡。那什么是有价值的 Trace 呢?依据日常排查教训,咱们发现业务研发次要关怀以下四类优先级高场景:

  • 在调用链上呈现了异样 ERROR;
  • 在调用链上呈现了大于「200ms」的数据库调用;
  • 整个调用链耗时超过「1s」;
  • 业务场景的调用链,比方通过订单号关联的调用链。

在这个背景下,并联合业界的实践经验,落地 Trace2.0 的过程中设计了尾部采样 & 冷热分层存储计划,计划如下:

  • 「3 天」内的 Trace 数据全量保留,定义为热数据。
  • 基于 Kafka 提早生产 +Bloom Filter 尾部采样的数据 (错、慢、自定义采样规定、以及默认惯例 0.1% 采样数据) 保留「30 天」,定义为冷数据。

整体解决流程如下:

  • OTel Server 数据收集 & 采样规定 :将客户端采集器上报的全量 Trace 数据实时写入 Kafka 中,并把满足采样规定(上述定义的场景) 的 Span 数据对应的 TraceID 记录到 Bloom Filter 中;
  • OTel Storage 长久化热数据:实时生产 Kafka 中数据,并全量长久化到 ClickHouse 热集群中;
  • OTel Storage 长久化冷数据:订阅上游 OTel Server 的 Bloom Filter,提早生产 Kafka 中的数据,将 TraceID 在 Bloom Filter 中可能存在的 Span 数据长久化到 ClickHouse 冷集群中;延迟时间配置的 30 分钟,尽量保障一个 Trace 下的 Span 残缺保留。
  • TraceID 点查: Trace2.0 自定义了 TraceID 的生成规定;在生成 TraceID 时,会把以后工夫戳秒数的 16 进制编码后果 (占 8 个字节) 作为 TraceID 的一部分。查问时只须要解码 TraceId 中的工夫戳,即可晓得应该查问热集群还是冷集群。

接下来再介绍一下尾部采样中 Bloom Filter 的设计细节,如下图所示:

整体解决流程如下:

  • OTel Server 会将满足采样规定的 Span 数据对应的 TraceID,依据 TraceID 中的工夫戳写入到对应工夫戳的 Bloom Filter 中;
  • Bloom Filter 会按十分钟粒度 (可依据理论的数据量并联合 BloomFilter 的误算率和样本大小计算内存耗费并调整) 进行分片,十分钟过后将 Bloom Filter 进行序列化并写入到 ClickHouse 存储中;
  • OTel Storage 生产侧拉取 Bloom Filter 数据 (留神:同一个工夫窗口,每一个 OTel Server 节点都会生成一个 BloomFilter) 并进行合并 Merge(缩小 Bloom Filter 的内存占用并进步 Bloom Filter 的查问效率)。

综上所述,Trace2.0 仅应用了较少的资源就实现了尾部采样和冷热分层存储。既为公司节约了老本,又保留了简直所有「有价值」Trace,解决了业务研发日常排查时查问不到想看的 Trace 的问题。

3. 自建存储 & 降本增效

3.1 基于 SLS-Trace 的解决方案

Trace2.0 建设初期采纳了 SLS 专为 OpenTelemetry 定制的 Trace 计划【1】,提供了 Trace 查问、调用剖析、拓扑剖析等性能,如下图所示:

SLS-Trace 次要解决流程如下:

  • 利用 OpenTelemetry Collector aliyunlogserverexporter【2】将 Trace 数据写入到 SLS-Trace Logstore 中;
  • SLS-Trace 通过默认提供的 Scheduled SQL 工作定时聚合 Trace 数据并生成相应的 Span 指标与利用、接口粒度的拓扑指标等数据。

随着 Trace2.0 在公司外部全面铺开,SLS 的存储老本压力变得越来越大,为了响应公司“利用技术手段实现降本提效”的号召,咱们决定自建存储。

3.2 基于 ClickHouse 的解决方案

目前业内比拟风行的全链路追踪开源我的项目 (SkyWalking、Pinpoint、Jaeger 等) 采纳的存储大都是基于 ES 或者 HBase 实现的。而近几年新兴的开源全链路追踪开源我的项目 (Uptrace【3】、Signoz【4】等) 采纳的存储大都是基于 ClickHouse 实现的,同时将 Span 数据荡涤进去的指标数据也存储在 ClickHouse 中。且 ClickHouse 的物化视图 (很好用) 也很好地解决了指标数据降采样 (DownSampling) 的问题。最终通过一番调研,咱们决定基于 ClickHouse 来自建新的存储解决方案。整体架构图如下:

整体解决流程如下:

  • Trace 索引 & 明细数据:OTel Storage 会将基于 Span 原始数据构建的索引数据写入到 SpanIndex 表中,将 Span 原始明细数据写入到 SpanData 表中(相干表设计能够参考 Uptrace【5】);
  • 计算 & 长久化 SpanMetrics 数据:OTel Storage 会依据 Span 的 Service、SpanName、Host、StatusCode 等属性统计并生成「30 秒」粒度的总调用次数、总耗时、最大耗时、最小耗时、分位线等指标数据,并写入到 SpanMetrics 表;

    • 指标 DownSampling 性能:利用 ClickHouse 的物化视图将「秒级」指标聚合成「分钟级」指标,再将「分钟级」指标聚合成「小时级」指标;从而实现多精度的指标以满足不同工夫范畴的查问需要;
-- span_metrics_10m_mv
CREATE MATERIALIZED VIEW IF NOT EXISTS '{database}'.span_metrics_10m_mv_local
            on cluster '{cluster}'
            TO '{database}'.span_metrics_10m_local
AS
SELECT a.serviceName                     as serviceName,
       a.spanName                        as spanName,
       a.kind                            as kind,
       a.statusCode                      as statusCode,
       toStartOfTenMinutes(a.timeBucket) as timeBucket,
       sum(a.count)                      as count,
       sum(a.timeSum)                    as timeSum,
       max(a.timeMax)                    as timeMax,
       min(a.timeMin)                    as timeMin
FROM '{database}'.span_metrics_30s_local as a
GROUP BY a.serviceName, a.spanName, a.kind, a.statusCode,
    toStartOfTenMinutes(a.timeBucket);
  • 元数据(上下游拓扑数据):OTel Storage 依据 Span 属性中的上下游关系(须要在客户端埋相干属性),将拓扑依赖关系写入到图数据库 Nebula 中。

ClickHouse 写入细节

ClickHouse 应用 Distributed 引擎实现了 Distributed(分布式)表机制,能够在所有分片 (本地表) 上建设视图,实现分布式查问。并且 Distributed 表本身不会存储任何数据,它会通过读取或写入其余远端节点的表来进行数据处理。SpanData 表创立语句如下所示:

-- span_data
CREATE TABLE IF NOT EXISTS '{database}'.span_data_local ON CLUSTER '{cluster}'
(traceID                   FixedString(32),
    spanID                    FixedString(16),
    startTime                 DateTime64(6) Codec (Delta, Default),
    body                      String CODEC (ZSTD(3))
) ENGINE = MergeTree
ORDER BY (traceID,startTime,spanID)
PARTITION BY toStartOfTenMinutes(startTime)
TTL toDate(startTime) + INTERVAL '{TTL}' HOUR;

-- span_data_distributed
CREATE TABLE IF NOT EXISTS '{database}'.span_data_all ON CLUSTER '{cluster}'
as '{database}'.span_data_local
    ENGINE = Distributed('{cluster}', '{database}', span_data_local,
                         xxHash64(concat(traceID,spanID,toString(toDateTime(startTime,6)))));

整体写入流程比较简单(留神:防止应用分布式表),如下所示:

  • 定时获取 ClickHouse 集群节点;
  • 通过 Hash 函数抉择对应的 ClickHouse 节点,而后批量写 ClickHouse 的本地表。

上线成果

全链路追踪是一个典型的写多读少的场景,因而咱们采纳了 ClickHouse ZSTD 压缩算法对数据进行了压缩,压缩后的压缩比高达 12,成果十分好。目前 ClickHouse 冷热集群各应用数十台 16C64G ESSD 机器,单机写入速度 25w/s(ClickHouse 写入的行数)。相比于初期的阿里云 SLS-Trace 计划,存储老本降落 66%,查问速度也从 800+ms 降落至 490+ms。

下一步布局

目前 Trace2.0 将 Span 的原始明细数据也存储在了 ClickHouse 中,导致 ClickHouse 的磁盘使用率会有些偏高,后续思考将 Span 明细数据先写入 HDFS/OSS 等块存储设备中,ClickHouse 来记录每个 Span 在块存储中的 offset,从而进一步升高 ClickHouse 的存储老本。

对于咱们:
得物监控团队提供一站式的可观测性平台,负责链路追踪、时序数据库、日志零碎,包含自定义大盘、利用大盘、业务监控、智能告警、AIOPS 等排障剖析。

欢送对可观测性 / 监控 / 告警 /AIOPS 等畛域感兴趣的同学退出咱们。

援用
【1】SLS-Trace 计划 https://developer.aliyun.com/…
【2】SLS-Trace Contrib https://github.com/open-telem…
【3】Uptrace https://uptrace.dev/
【4】Signoz https://signoz.io/
【5】Uptrace Schema 设计 https://github.com/uptrace/up…

本篇是 《得物云原生全链路追踪 Trace2.0》 系列开篇,更多内容请关注“得物技术”公众号。
得物云原生全链路追踪 Trace2.0 架构实际
得物云原生全链路追踪 Trace2.0 产品篇
得物云原生全链路追踪 Trace2.0 采集篇
得物云原生全链路追踪 Trace2.0 数据挖掘篇

* 文 / 南风
@得物技术公众号

正文完
 0