得物云原生全鏈路追蹤Trace2.0架構(gòu)實(shí)踐

文|南風(fēng) 得物技術(shù)

導(dǎo)讀:

分布式鏈路追蹤作為解決分布式應(yīng)用可觀測(cè)問(wèn)題的重要技術(shù),得物全鏈路追蹤(簡(jiǎn)稱(chēng)Trace2.0)基于OpenTelemetry提供的可觀測(cè)標(biāo)準(zhǔn)方案實(shí)現(xiàn)新一代的一站式全鏈路觀測(cè)診斷平臺(tái),并通過(guò)全量采集Trace幫助業(yè)務(wù)提高故障診斷、性能優(yōu)化、架構(gòu)治理的效率。

全量采集Trace數(shù)據(jù)(日增數(shù)百TB 、數(shù)千億條Span數(shù)據(jù))并以較低的成本保證數(shù)據(jù)的實(shí)時(shí)處理與高效查詢,對(duì)Trace2.0后端整體的可觀測(cè)性解決方案提出了極高的要求。本文將詳細(xì)介紹Trace2.0背后的架構(gòu)設(shè)計(jì)、尾部采樣和冷熱存儲(chǔ)方案,以及我們是如何通過(guò)自建存儲(chǔ)實(shí)現(xiàn)進(jìn)一步的降本增效(存儲(chǔ)成本下降66%)。

1. 整體架構(gòu)設(shè)計(jì)

image.png

全鏈路追蹤Trace2.0從數(shù)據(jù)接入側(cè)、計(jì)算、存儲(chǔ)到查詢整體模塊架構(gòu)如上圖所示。這里說(shuō)一下各組件的核心能力:

  • 客戶端&數(shù)據(jù)采集:集成并定制OpenTelemetry提供的多語(yǔ)言SDK(Agent),生成統(tǒng)一格式的可觀測(cè)數(shù)據(jù)。
  • 控制平面Control Plane:統(tǒng)一的配置中心向數(shù)據(jù)采集側(cè)下發(fā)各類(lèi)動(dòng)態(tài)配置發(fā)并實(shí)時(shí)生效;支持向各采集器下發(fā)動(dòng)態(tài)配置并實(shí)時(shí)生效,支持應(yīng)用按實(shí)例數(shù)灰度接入,并提供出入?yún)⑹占瘎?dòng)態(tài)開(kāi)關(guān)、性能剖析動(dòng)態(tài)開(kāi)關(guān)、流量染色動(dòng)態(tài)配置、客戶端版本管理等。
  • 數(shù)據(jù)收集服務(wù)OTel Server:數(shù)據(jù)收集器OTel Server兼容OpenTelemetry Protocol(OTLP)協(xié)議,提供gRPC和HTTP兩種方式接收采集器發(fā)送的可觀測(cè)數(shù)據(jù)。
  • 分析計(jì)算&存儲(chǔ)OTel Storage:計(jì)算側(cè)除了基礎(chǔ)的實(shí)時(shí)檢索能力外,還提供了場(chǎng)景化的數(shù)據(jù)分析計(jì)算主要包括:

a.存儲(chǔ)Trace數(shù)據(jù):數(shù)據(jù)分為兩段,一段是索引字段,包括TraceID、ServiceName、SpanName、StatusCode、Duration和起止時(shí)間等基本信息,用于高級(jí)檢索;另一段是明細(xì)數(shù)據(jù)(源數(shù)據(jù),包含所有的Span數(shù)據(jù))

b.計(jì)算SpanMetrics數(shù)據(jù):聚合計(jì)算Service、SpanName、Host、StatusCode、Env、Region等維度的執(zhí)行總次數(shù)、總耗時(shí)、最大耗時(shí)、最小耗時(shí)、分位線等數(shù)據(jù);

c.業(yè)務(wù)單號(hào)關(guān)聯(lián)Trace:電商場(chǎng)景下部分研發(fā)多以訂單號(hào)、履約單號(hào)、匯金單號(hào)作為排障的輸入,因此和業(yè)務(wù)研發(fā)約定特殊埋點(diǎn)規(guī)則后--在Span的Tag里添加一個(gè)特殊字段"bizOrderId={實(shí)際單號(hào)}"--便將這個(gè)Tag作為ClickHouse的索引字段;從而實(shí)現(xiàn)業(yè)務(wù)鏈路到全鏈路Trace形成一個(gè)完整的排障鏈路;

d.Redis熱點(diǎn)數(shù)據(jù)統(tǒng)計(jì):在客戶端側(cè)擴(kuò)展調(diào)用Redis時(shí)入?yún)⒑统鰠panTag埋點(diǎn),以便統(tǒng)Redis命中率、大Key、高頻寫(xiě)、慢調(diào)用等指標(biāo)數(shù)據(jù);

e.MySQL熱點(diǎn)數(shù)據(jù)統(tǒng)計(jì):按照SQL指紋統(tǒng)計(jì)調(diào)用次數(shù)、慢SQL次數(shù)以及關(guān)聯(lián)的接口名。

2. 尾部采樣&冷熱存儲(chǔ)

得物早期的全鏈路追蹤方案出于對(duì)存儲(chǔ)成本的考慮,在客戶端設(shè)置了1%的采樣率,導(dǎo)致研發(fā)排查問(wèn)題時(shí)經(jīng)常查詢不到想看的Trace鏈路。那么Trace2.0為了解決這個(gè)問(wèn)題,就不能僅僅只是簡(jiǎn)單地將客戶端的采樣率調(diào)整為100%,而是需要在客戶端全量采集Trace數(shù)據(jù)的同時(shí),合理地控制Trace存儲(chǔ)成本。且從實(shí)踐經(jīng)驗(yàn)來(lái)看,Trace數(shù)據(jù)的價(jià)值分布是不均勻的,隨著時(shí)間的推移Trace的數(shù)據(jù)價(jià)值是急速降低的。

全量存儲(chǔ)Trace數(shù)據(jù)不僅會(huì)造成巨大的成本浪費(fèi),還會(huì)顯著地影響整條數(shù)據(jù)處理鏈路的性能以及穩(wěn)定性。所以,如果我們能夠只保存那些有價(jià)值、大概率會(huì)被用戶實(shí)際查詢的Trace,就能取得成本與收益的平衡。那什么是有價(jià)值的Trace呢?根據(jù)日常排查經(jīng)驗(yàn),我們發(fā)現(xiàn)業(yè)務(wù)研發(fā)主要關(guān)心以下四類(lèi)優(yōu)先級(jí)高場(chǎng)景:

  • 在調(diào)用鏈上出現(xiàn)了異常ERROR;
  • 在調(diào)用鏈上出現(xiàn)了大于「200ms」的數(shù)據(jù)庫(kù)調(diào)用;
  • 整個(gè)調(diào)用鏈耗時(shí)超過(guò)「1s」;
  • 業(yè)務(wù)場(chǎng)景的調(diào)用鏈,比如通過(guò)訂單號(hào)關(guān)聯(lián)的調(diào)用鏈。

在這個(gè)背景下,并結(jié)合業(yè)界的實(shí)踐經(jīng)驗(yàn),落地Trace2.0的過(guò)程中設(shè)計(jì)了尾部采樣&冷熱分層存儲(chǔ)方案,方案如下:

  • 「3天」內(nèi)的Trace數(shù)據(jù)全量保存,定義為熱數(shù)據(jù)。
  • 基于Kafka延遲消費(fèi)+Bloom Filter尾部采樣的數(shù)據(jù)(錯(cuò)、慢、自定義采樣規(guī)則、以及默認(rèn)常規(guī)0.1%采樣數(shù)據(jù))保留「30天」,定義為冷數(shù)據(jù)。
image.png

整體處理流程如下:

  • OTel Server數(shù)據(jù)收集&采樣規(guī)則:將客戶端采集器上報(bào)的全量Trace數(shù)據(jù)實(shí)時(shí)寫(xiě)入Kafka中,并把滿足采樣規(guī)則(上述定義的場(chǎng)景)的Span數(shù)據(jù)對(duì)應(yīng)的TraceID記錄到Bloom Filter中;

  • OTel Storage持久化熱數(shù)據(jù):實(shí)時(shí)消費(fèi)Kafka中數(shù)據(jù),并全量持久化到ClickHouse熱集群中;

  • OTel Storage持久化冷數(shù)據(jù):訂閱上游OTel Server的Bloom Filter,延遲消費(fèi)Kafka中的數(shù)據(jù),將TraceID在Bloom Filter中可能存在的Span數(shù)據(jù)持久化到ClickHouse冷集群中;

  • 延遲時(shí)間配置的30分鐘,盡量保證一個(gè)Trace下的Span完整保留。

  • TraceID點(diǎn)查: Trace2.0自定義了TraceID的生成規(guī)則;在生成TraceID時(shí),會(huì)把當(dāng)前時(shí)間戳秒數(shù)的16進(jìn)制編碼結(jié)果(占8個(gè)字節(jié))作為T(mén)raceID的一部分。查詢時(shí)只需要解碼TraceId中的時(shí)間戳,即可知道應(yīng)該查詢熱集群還是冷集群。

接下來(lái)再介紹一下尾部采樣中Bloom Filter的設(shè)計(jì)細(xì)節(jié),如下圖所示:

image.png

整體處理流程如下:

a. OTel Server會(huì)將滿足采樣規(guī)則的Span數(shù)據(jù)對(duì)應(yīng)的TraceID,根據(jù)TraceID中的時(shí)間戳寫(xiě)入到對(duì)應(yīng)時(shí)間戳的Bloom Filter中;

b. Bloom Filter會(huì)按十分鐘粒度(可根據(jù)實(shí)際的數(shù)據(jù)量并結(jié)合BloomFilter的誤算率和樣本大小計(jì)算內(nèi)存消耗并調(diào)整)進(jìn)行分片,十分鐘過(guò)后將Bloom Filter進(jìn)行序列化并寫(xiě)入到ClickHouse存儲(chǔ)中;

c. OTel Storage消費(fèi)側(cè)拉取Bloom Filter數(shù)據(jù)(注意:同一個(gè)時(shí)間窗口,每一個(gè)OTel Server節(jié)點(diǎn)都會(huì)生成一個(gè)BloomFilter)并進(jìn)行合并Merge(減少Bloom Filter的內(nèi)存占用并提高Bloom Filter的查詢效率)。

綜上所述,Trace2.0僅使用了較少的資源就完成了尾部采樣和冷熱分層存儲(chǔ)。既為公司節(jié)約了成本,又保存了幾乎所有「有價(jià)值」Trace,解決了業(yè)務(wù)研發(fā)日常排查時(shí)查詢不到想看的Trace的問(wèn)題。

3. 自建存儲(chǔ)&降本增效

3.1 基于SLS-Trace的解決方案

Trace2.0建設(shè)初期采用了*SLS專(zhuān)為OpenTelemetry定制的Trace方案 *【1】,提供了Trace查詢、調(diào)用分析、拓?fù)浞治龅裙δ埽缦聢D所示:

image.png

SLS-Trace主要處理流程如下:

a. 利用OpenTelemetry Collector aliyunlogserverexporter【2】將Trace數(shù)據(jù)寫(xiě)入到SLS-Trace Logstore中;

b. SLS-Trace通過(guò)默認(rèn)提供的Scheduled SQL任務(wù)定時(shí)聚合Trace數(shù)據(jù)并生成相應(yīng)的Span指標(biāo)與應(yīng)用、接口粒度的拓?fù)渲笜?biāo)等數(shù)據(jù)。

隨著Trace2.0在公司內(nèi)部全面鋪開(kāi),SLS的存儲(chǔ)成本壓力變得越來(lái)越大,為了響應(yīng)公司“利用技術(shù)手段實(shí)現(xiàn)降本提效”的號(hào)召,我們決定自建存儲(chǔ)。

3.2 基于ClickHouse的解決方案

目前業(yè)內(nèi)比較流行的全鏈路追蹤開(kāi)源項(xiàng)目(SkyWalking、Pinpoint、Jaeger等)采用的存儲(chǔ)大都是基于ES或者HBase實(shí)現(xiàn)的。而近幾年新興的開(kāi)源全鏈路追蹤開(kāi)源項(xiàng)目(Uptrace【3】、Signoz【4】等)采用的存儲(chǔ)大都是基于ClickHouse實(shí)現(xiàn)的,同時(shí)將Span數(shù)據(jù)清洗出來(lái)的指標(biāo)數(shù)據(jù)也存儲(chǔ)在ClickHouse中。且ClickHouse的物化視圖(很好用)也很好地解決了指標(biāo)數(shù)據(jù)降采樣(DownSampling)的問(wèn)題。最終經(jīng)過(guò)一番調(diào)研,我們決定基于ClickHouse來(lái)自建新的存儲(chǔ)解決方案。整體架構(gòu)圖如下:

image.png

整體處理流程如下:

  • Trace索引&明細(xì)數(shù)據(jù):OTel Storage會(huì)將基于Span原始數(shù)據(jù)構(gòu)建的索引數(shù)據(jù)寫(xiě)入到SpanIndex表中,將Span原始明細(xì)數(shù)據(jù)寫(xiě)入到SpanData表中(相關(guān)表設(shè)計(jì)可以參考Uptrace【5】);
  • 計(jì)算&持久化SpanMetrics數(shù)據(jù):OTel Storage會(huì)根據(jù)Span的Service、SpanName、Host、StatusCode等屬性統(tǒng)計(jì)并生成「30秒」粒度的總調(diào)用次數(shù)、總耗時(shí)、最大耗時(shí)、最小耗時(shí)、分位線等指標(biāo)數(shù)據(jù),并寫(xiě)入到SpanMetrics表;

指標(biāo)DownSampling功能:利用ClickHouse的物化視圖將「秒級(jí)」指標(biāo)聚合成「分鐘級(jí)」指標(biāo),再將「分鐘級(jí)」指標(biāo)聚合成「小時(shí)級(jí)」指標(biāo);從而實(shí)現(xiàn)多精度的指標(biāo)以滿足不同時(shí)間范圍的查詢需求;

-- 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);
  • 元數(shù)據(jù)(上下游拓?fù)鋽?shù)據(jù)):OTel Storage根據(jù)Span屬性中的上下游關(guān)系(需要在客戶端埋相關(guān)屬性),將拓?fù)湟蕾?lài)關(guān)系寫(xiě)入到圖數(shù)據(jù)庫(kù)Nebula中。

ClickHouse寫(xiě)入細(xì)節(jié)

ClickHouse使用Distributed引擎實(shí)現(xiàn)了Distributed(分布式)表機(jī)制,可以在所有分片(本地表)上建立視圖,實(shí)現(xiàn)分布式查詢。并且Distributed表自身不會(huì)存儲(chǔ)任何數(shù)據(jù),它會(huì)通過(guò)讀取或?qū)懭肫渌h(yuǎn)端節(jié)點(diǎn)的表來(lái)進(jìn)行數(shù)據(jù)處理。SpanData表創(chuàng)建語(yǔ)句如下所示:

-- 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)))));

整體寫(xiě)入流程比較簡(jiǎn)單(注意:避免使用分布式表),如下所示:

  • 定時(shí)獲取ClickHouse集群節(jié)點(diǎn);
  • 通過(guò)Hash函數(shù)選擇對(duì)應(yīng)的ClickHouse節(jié)點(diǎn),然后批量寫(xiě)ClickHouse的本地表。
image.png

上線效果

全鏈路追蹤是一個(gè)典型的寫(xiě)多讀少的場(chǎng)景,因此我們采用了ClickHouse ZSTD壓縮算法對(duì)數(shù)據(jù)進(jìn)行了壓縮,壓縮后的壓縮比高達(dá)12,效果非常好。目前ClickHouse冷熱集群各使用數(shù)十臺(tái)16C64G ESSD機(jī)器,單機(jī)寫(xiě)入速度25w/s(ClickHouse寫(xiě)入的行數(shù))。相比于初期的阿里云SLS-Trace方案,存儲(chǔ)成本下降66%,查詢速度也從800+ms下降至490+ms。

下一步規(guī)劃

目前Trace2.0將Span的原始明細(xì)數(shù)據(jù)也存儲(chǔ)在了ClickHouse中,導(dǎo)致ClickHouse的磁盤(pán)使用率會(huì)有些偏高,后續(xù)考慮將Span明細(xì)數(shù)據(jù)先寫(xiě)入HDFS/OSS等塊存儲(chǔ)設(shè)備中,ClickHouse來(lái)記錄每個(gè)Span在塊存儲(chǔ)中的offset,從而進(jìn)一步降低ClickHouse的存儲(chǔ)成本。

關(guān)于我們:

得物監(jiān)控團(tuán)隊(duì)提供一站式的可觀測(cè)性平臺(tái),負(fù)責(zé)鏈路追蹤、時(shí)序數(shù)據(jù)庫(kù)、日志系統(tǒng),包括自定義大盤(pán)、應(yīng)用大盤(pán)、業(yè)務(wù)監(jiān)控、智能告警、AIOPS等排障分析。

歡迎對(duì)可觀測(cè)性/監(jiān)控/告警/AIOPS 等領(lǐng)域感興趣的同學(xué)加入我們。

引用

【1】SLS-Trace方案

https://developer.aliyun.com/article/785854

【2】SLS-Trace Contrib

https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/alibabacloudlogserviceexporter

【3】Uptrace

https://uptrace.dev/

【4】Signoz

https://signoz.io/

【5】Uptrace Schema設(shè)計(jì)

https://github.com/uptrace/uptrace/tree/v0.2.16/pkg/bunapp/migrations

本篇是《得物云原生全鏈路追蹤Trace2.0》系列開(kāi)篇,更多內(nèi)容請(qǐng)關(guān)注“得物技術(shù)”公眾號(hào)。

  • 得物云原生全鏈路追蹤Trace2.0架構(gòu)實(shí)踐

  • 得物云原生全鏈路追蹤Trace2.0產(chǎn)品篇

  • 得物云原生全鏈路追蹤Trace2.0采集篇

  • 得物云原生全鏈路追蹤Trace2.0數(shù)據(jù)挖掘篇

*文/南風(fēng)

關(guān)注得物技術(shù),每周一三五晚18:30更新技術(shù)干貨
要是覺(jué)得文章對(duì)你有幫助的話,歡迎評(píng)論轉(zhuǎn)發(fā)點(diǎn)贊

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容