得物App全棧 DevOps 可觀測平臺(tái)落地實(shí)踐
得物 App 是 2015 年上線的,初衷創(chuàng)建一個(gè)更加年輕、更加時(shí)尚、潮流的社區(qū)平臺(tái),其中創(chuàng)造性的引入了鑒別的方式解決在交易過程中遇到的問題,最近幾年逐步從球鞋品類把他過渡到服裝、箱包、化妝品等,到今天為止得物 App 它就不是一個(gè)簡單的是球鞋交易平臺(tái),而是一個(gè)全品類綜合性的電商平臺(tái)。隨著業(yè)務(wù)規(guī)模和復(fù)雜度的增加,監(jiān)控的規(guī)模也隨之?dāng)U大。
在 4 月 22 日 ArchSummit(上海站)架構(gòu)師峰會(huì)上,得物 App 監(jiān)控平臺(tái)架構(gòu)師李尊和大家分享了得物在可觀測性領(lǐng)域的一些工作成果。(7 月 21-22 日深圳站 ArchSummit 會(huì)議在籌備中,歡迎點(diǎn)擊“閱讀原文”關(guān)注)文末有彩蛋。

得物的技術(shù)棧主要是 Java 和 Go,在 2021 年前主要選擇當(dāng)時(shí)業(yè)界比較流行的監(jiān)控開源產(chǎn)品,像日志選擇 Loki,指標(biāo)基于 Prometheus 生態(tài),應(yīng)用上報(bào)到注冊中心后可實(shí)現(xiàn)自動(dòng)化采集,存儲(chǔ)選擇 VictoriaMetrics,Trace 基于 Jaeger,采用組合采樣策略,頭部采樣和每分鐘固定采樣,最終采樣率在 3% 左右,大盤基于 Grafana 構(gòu)建。
2021 年我們開始制定標(biāo)準(zhǔn)進(jìn)行監(jiān)控治理,結(jié)合排查經(jīng)驗(yàn),引入應(yīng)用監(jiān)控,提供異常分析、慢 MySQL 統(tǒng)計(jì)和 Redis 熱點(diǎn)分析,包括命中率、大 Key。
2022 年針對(duì)監(jiān)控各個(gè)領(lǐng)域?qū)m?xiàng)做深度迭代和打磨,比如 Trace,解決采樣率低問題, 全量上報(bào)后通過尾部采樣解決冷熱存儲(chǔ)問題以及引入 OSS 將存儲(chǔ)成本降低 90%。另一方面在數(shù)據(jù)聯(lián)動(dòng)上指標(biāo)和 Trace 缺乏強(qiáng)關(guān)聯(lián)性,引入 OT 打造端到端的鏈路追蹤。在標(biāo)準(zhǔn)協(xié)議下實(shí)現(xiàn)指標(biāo)關(guān)聯(lián) Trace,Trace 關(guān)聯(lián)日志,在產(chǎn)品側(cè)實(shí)現(xiàn)下鉆分析。產(chǎn)品層開始擺脫 Grafana 的依賴,圖表基于 antv 構(gòu)建。

整個(gè) 2022 年我們在數(shù)據(jù)質(zhì)量方面和架構(gòu)方面做了一個(gè)巨大的調(diào)整,主要是為了我們在 2023 年建設(shè)全息監(jiān)控做準(zhǔn)備,第一基于應(yīng)用的這套體系快速的覆蓋到中間件,包括 k8s,實(shí)現(xiàn)指標(biāo)的標(biāo)準(zhǔn)化,大盤的標(biāo)準(zhǔn)化,告警的標(biāo)準(zhǔn)化。再就是我們要以應(yīng)用為中心,搭建一個(gè)可觀性平臺(tái),通過以應(yīng)用為中心構(gòu)建一個(gè)元數(shù)據(jù)中心,同時(shí)基于 Trace 構(gòu)建整個(gè)業(yè)務(wù)拓?fù)鋱D,得到整個(gè)知識(shí)圖譜實(shí)現(xiàn)一個(gè)全息監(jiān)控。
通過 Trace 打通了所有層的關(guān)聯(lián),基于這些關(guān)聯(lián)關(guān)系將元數(shù)據(jù)與異常倉庫進(jìn)行關(guān)聯(lián)支撐整個(gè)得物 NOC-SLA 的體系建設(shè), 完成“1-5-10”的目標(biāo),并且在系統(tǒng)治理和用戶體驗(yàn)上面得到一個(gè)很大的提升。
要實(shí)現(xiàn)一個(gè)鏈路追蹤系統(tǒng),我們首先要解決的就是數(shù)據(jù)采集的問題,早期得物的鏈路追蹤使用 SDK 方式,升級(jí)起來比較麻煩,所以我們新的鏈路追蹤就希望使用 Java Agent 采用字節(jié)碼增強(qiáng)的方式,對(duì)應(yīng)用透明,然后當(dāng)時(shí)市面上基于 Java Agent 字節(jié)碼增強(qiáng)實(shí)現(xiàn)比較成熟的有 Pinpoint、Skywalking 和 OpenTelemetry。

那 OpenTelemetry 是 CNCF 云原生基金會(huì)里面的項(xiàng)目,它規(guī)范了各觀測數(shù)據(jù)的類型,以及采集和導(dǎo)出的一個(gè)標(biāo)準(zhǔn)方法,其中包括 Trace、Metric、Log,如果基于 OpenTelemetry 的話,我們就可以通過一套標(biāo)準(zhǔn)的方案將 Trace、Metric、Log 進(jìn)行生成和導(dǎo)出,然后可以將這些不同類型的數(shù)據(jù)友好的把它關(guān)聯(lián)起來,從而降低我們在開發(fā)過程中對(duì)不同類型的觀察數(shù)據(jù)的使用成本,且無縫兼容現(xiàn)有的主流可觀測性系統(tǒng),比如 Prometheus、OpenTracing。
同時(shí)國內(nèi)外各大廠商都在適配它,包括谷歌、微軟、阿里云、騰訊云等,不依賴任何特定的廠商,然后我們團(tuán)隊(duì)也比較看好 OpenTelemetry 以后的一個(gè)發(fā)展趨勢,并且希望跟進(jìn) OpenTelemetry 的社區(qū)享受社區(qū)帶來的技術(shù)紅利和影響力,最終我們選擇了基于 OpenTelemetry 來建設(shè)得物的 Trace2.0。

采集端:通過集成并定制 OT 提供的多語言 SDK(Agent),生成統(tǒng)一格式的數(shù)據(jù)。目前支持 Java\Go\Python\JS 四個(gè)語言。
控制平面:中心化的配置中心向采集側(cè)下發(fā)各類配置并動(dòng)態(tài)生效;支持應(yīng)用按實(shí)例數(shù)灰度接入,并提供出入?yún)?dòng)態(tài)開關(guān)、性能剖析、版本管理等
數(shù)據(jù)網(wǎng)關(guān):OTel Server 兼容 OT 協(xié)議,提供 gRPC 和 HTTP 兩種方式, 并將數(shù)據(jù)寫入 Kafka
計(jì)算側(cè):除了將 Span 數(shù)據(jù)落盤之外,還提供了場景化的數(shù)據(jù)分析能力包括:SpanMetric 的計(jì)算、Redis 熱點(diǎn)分析、MySQL 熱點(diǎn)分析、單號(hào)關(guān)聯(lián) Trace
存儲(chǔ)側(cè):主要引入對(duì)象存儲(chǔ),Trace 的索引數(shù)據(jù)存放在 ClickHouse 中,明細(xì)數(shù)據(jù)存放 OSS,元數(shù)據(jù)存放在圖數(shù)據(jù)庫中

首先最重要的就是 Trace2.0 保存所有有價(jià)值的一個(gè) Trace 的完整的鏈路,那哪些是有價(jià)值的 Trace,后面也會(huì)給大家詳細(xì)的介紹,同時(shí) Trace2.0 支持各類型監(jiān)控的一個(gè)關(guān)聯(lián),就可以實(shí)現(xiàn)指標(biāo)關(guān)聯(lián) Trace,Trace 關(guān)聯(lián)日志,然后采集端基于 JavaAgent 構(gòu)建,接入只需要添加一個(gè) JVM 參數(shù)就可以了,后續(xù)升級(jí)就比較方便,對(duì)應(yīng)用無感知,Trace2.0 還提供了請求的出入?yún)ⅰ?yīng)用自定義埋點(diǎn)、診斷工具等方面的能力。
第一階段 Trace 的明細(xì)完全基于 ClickHouse 構(gòu)建,分別是 SpanIndex 表和 SpanData 表,SpanIndex 用于高級(jí)檢索,SpanData 存儲(chǔ)每個(gè) Span 的明細(xì)數(shù)據(jù),為什么選擇 ClickHouse 呢,ClickHouse 每秒鐘可以寫入數(shù)百萬甚至數(shù)千萬行數(shù)據(jù)。全量采集下寫入能力還是非常重要的,此外稀疏索引可以提供更好的查詢性能和內(nèi)存占用。

第二階段我們對(duì) Trace 數(shù)據(jù)做了冷熱分離,對(duì)于履約系統(tǒng)經(jīng)常需要排查超過 7 天的場景,為此我們做了冷熱存儲(chǔ),近 7 天的數(shù)據(jù)全量保存,超過 7 天的只保留有價(jià)值的數(shù)據(jù),為什么選擇基于 kafka 的延遲消費(fèi)方式呢,主要是當(dāng)前市面的的尾部采樣都是在端側(cè)決策,這對(duì)異常場景不友好,容易導(dǎo)致 Trace 保留不全,無法保障完整的鏈路。
第二階段的 Trace 數(shù)據(jù)還是保留在 ClickHouse 中,雖然采用冷熱存儲(chǔ)解決了長時(shí)間保留的問題,但 ClickHouse 使用 SSD 盤價(jià)格也不低,第三階段我們引入對(duì)象存儲(chǔ)進(jìn)一步的把 Trace 存儲(chǔ)成本降低。
下面來詳細(xì)介紹下冷熱存儲(chǔ)和對(duì)象存儲(chǔ):
冷熱存儲(chǔ)主要基于 Kafka 的延遲消費(fèi)和 Bloomfilter 編碼,數(shù)據(jù)網(wǎng)關(guān)將客戶端上報(bào) Trace 數(shù)據(jù)寫入到 Kafka 中,并把滿足采樣規(guī)則(主要是錯(cuò)慢的 Trace)TraceID 通過 BloomFilter 編碼寫入 DB 中;
熱集群實(shí)時(shí)消費(fèi) Kafka 中的數(shù)據(jù),并持久化到 ClickHouse 中,保留 7 天;
冷集群延遲消費(fèi) Kafka 中的數(shù)據(jù),通過 BloomFilter 判斷 TraceID 是否命中,命中則寫入 ClickHouse 中,保留 30 天;

相關(guān)設(shè)計(jì)細(xì)節(jié)可以參考《得物云原生全鏈路追蹤Trace2.0架構(gòu)實(shí)踐》
如何降低 Trace 的存儲(chǔ)成本,第一個(gè)想到的開源項(xiàng)目就是 Grafana 的 Tempo,Tempo 使用對(duì)象存儲(chǔ) (索引和明細(xì)),并兼容一些主流協(xié)議像 Zipkin,Jaeger,OpenTelemetry,綜合考慮后決定引入對(duì)象存儲(chǔ),將索引放在 ClickHouse 中,明細(xì)存放在對(duì)象存儲(chǔ)中。

從 Kafka 消費(fèi) Span 后,并將 Span 先寫內(nèi)存,當(dāng)內(nèi)存滿足一定條件后會(huì)對(duì)這批 Span 數(shù)據(jù)進(jìn)行 ZSTD 壓縮后刷盤到對(duì)象存儲(chǔ) OSS 后。為什么不采用一個(gè) Trace 一個(gè)文件呢?為了防止 OSS 小文件過多,寫 OSS 采用追加寫方式,每次寫入可獲得 OSS 的文件名和偏移量,將地理位置存儲(chǔ) ClickHouse
中。
查詢時(shí),先通過 clickhouse 確定一個(gè) TraceId 都在哪些 OSS 文件塊中,根據(jù)文件塊地址通過隨機(jī)讀方式將文件塊下載到本地,注意這里是文件塊,不是文件,再通過塊內(nèi)偏移量解析每個(gè) Span。這樣就可以得到一個(gè)完整的 Trace。

這里需要注意文件塊的大小,一次批量寫會(huì)包含不同 Trace 下的 span,如果文件塊過大,會(huì)導(dǎo)致解壓時(shí)間過長,查詢會(huì)超時(shí),測下來文件塊設(shè)置 4MB 是一個(gè)比較合適的值。
Trace2.0 在得物落地一年多時(shí)間,現(xiàn)已覆蓋公司絕大部分在線業(yè)務(wù)。
每秒 TPS 在 12M/s 個(gè) Span
Trace 點(diǎn)查 P50 耗時(shí)在 300ms, P90 查詢耗時(shí)在 800ms
每天日增數(shù)據(jù)量在 700+TB
熱存保留 6 天總存儲(chǔ) 4PB、冷存保留 30 天存儲(chǔ) 1PB,采用 ZSTD 壓縮比在 12,
ClickHouse 單機(jī)可支持每秒 40w 個(gè) Span 寫入
第一個(gè)案例的話就是我們前后端鏈路打通的能力,在前后端沒有打通之前,當(dāng)前端收到一個(gè)異常后,我們無法全面地了解系統(tǒng)的性能狀況,無法監(jiān)控請求的傳輸路徑和處理時(shí)間,也無法對(duì)系統(tǒng)的性能指標(biāo)進(jìn)行全面的分析。

為了解決這個(gè)痛點(diǎn)的話,我們做了前后端的鏈路打通。這邊是一個(gè)效果圖,前端的異常就可以看到后端的鏈路,關(guān)聯(lián)了哪些服務(wù),通過出入?yún)⒖梢院芊奖愕呐挪閱栴}。同時(shí)提供了接口分析和頁面分析。另外也支持會(huì)話跟蹤,當(dāng)出現(xiàn)問題時(shí)通過 SessionID 實(shí)現(xiàn)全鏈路追蹤,還原用戶的行為軌跡,包括頁面加載、接口請求、和用戶操作等。
隨著公司應(yīng)用全面容器化,對(duì)于 K8s 集群的穩(wěn)定性要求越來越高,但是針對(duì) K8s 監(jiān)控沒有一個(gè)專業(yè)和全面的監(jiān)控產(chǎn)品滿足問題發(fā)現(xiàn)和故障定位。

早期 K8s 監(jiān)控大盤基于 Grafana 構(gòu)建,指標(biāo)理解和大盤配置門檻較高,且監(jiān)控面板比較分散,SRE 積累的排障工具無法與監(jiān)控產(chǎn)品做融合,圖表無下鉆能力,為此打造一款專業(yè)的 K8s 監(jiān)控產(chǎn)品,統(tǒng)一指標(biāo)計(jì)算口徑,對(duì)現(xiàn)有指標(biāo)做好分類分級(jí),單擊單個(gè)集群視角可查看關(guān)聯(lián)資源池監(jiān)控,資源池可下鉆分析單個(gè) Node 節(jié)點(diǎn)的監(jiān)控,POD 視角可關(guān)聯(lián)查看 Node 相關(guān)監(jiān)控,大盤之間可進(jìn)行聯(lián)動(dòng)分析,以及提供控制平面 API-Server 和 etcd 的監(jiān)控。
講完 K8S 監(jiān)控我們再看看應(yīng)用監(jiān)控,首先我們來看下接口分析,接口我們按照組件類型分為接口、下游調(diào)用、SQL 調(diào)用、NoSQL 調(diào)用、以及 MQ 和其他進(jìn)行分類。

圖表右側(cè)展示接口的黃金三指標(biāo),底下展示接口關(guān)聯(lián)的 Trace,接口支持的實(shí)例維度、上下游分析和耗時(shí)分解等排查場景。有了耗時(shí)分解我們就可以很清晰的看出接口 RT 變高,是由哪類操作類型導(dǎo)致,DB 還是 Redis,以及關(guān)聯(lián)的 Trace。
接下來介紹應(yīng)用監(jiān)控下另外一個(gè)非常重要的模塊“異常分析”,第一個(gè)是基于異常日志按照異常名進(jìn)行統(tǒng)計(jì)分析。

第二個(gè)是錯(cuò)誤碼分析,主要根據(jù)響應(yīng)體里的 Code 碼和 CodeMessage,通過對(duì)業(yè)務(wù)碼分類,可以快速的幫助我們了解業(yè)務(wù)需求和業(yè)務(wù)流程,有助于問題的發(fā)現(xiàn)和定位。
第三塊是 MySQL 熱點(diǎn)分析,按照 SQL 指紋統(tǒng)計(jì)調(diào)用次數(shù)、慢 SQL 次數(shù)以及關(guān)聯(lián)的接口名。
第四塊是 Redis 熱點(diǎn)分析,通過客戶端記錄 Redis 的入?yún)⒑统鰠ⅲy(tǒng)計(jì) Redis 命中率、大 Key、高頻寫、慢調(diào)用。
接下來介紹下應(yīng)用監(jiān)控的鏈路 Trace 部分。用戶可以在接口分析頁的黃金三指標(biāo)曲線上點(diǎn)擊就能看到對(duì)應(yīng)的 Trace 鏈路。同時(shí)也在接口頁面的右下角展示 Trace 檢索頁,可以快速的看出錯(cuò)、慢 Trace。

此外提供高級(jí)檢索模式,滿足研發(fā)自定義查詢場景,支持多維查詢,比如實(shí)例、或者指定上游或者指定下游進(jìn)行過濾。
此外,在電商場景下,研發(fā)多以訂單號(hào)、作為排障的場景,因此我們和研發(fā)團(tuán)隊(duì)約定埋點(diǎn)規(guī)則 ——在 Span 的 Tag 上記錄單號(hào)—— 便會(huì)在 ClickHouse 中新寫一條“單號(hào)關(guān)聯(lián)表”。用于記錄單號(hào) ID 和 TraceID 的映射關(guān)系,研發(fā)通過單號(hào)查看所有的 Trace。
Trace 詳情頁的話會(huì)將一個(gè) Trace 下的所有 Span 在一張圖中顯示摘要信息根據(jù) TraceID 解碼當(dāng)前鏈路的發(fā)生時(shí)間和來源 IP。

目前我們提供兩種展示模式,列表詳情以及聚合統(tǒng)計(jì)。
在聚合統(tǒng)計(jì)模式下,可以查看 trace 的整體性能指標(biāo),這次請求經(jīng)過哪些服務(wù),以及該服務(wù)請求了哪些組件,可以直觀的看出哪個(gè)服務(wù)耗時(shí)最高以及耗時(shí)最大的接口是哪個(gè)。
列表模式下支持自定義列,通過自定義可以快速的幫助我們理解 Trace 上下文,比如在染色環(huán)境下,測試同學(xué)想一眼看出當(dāng)前鏈路是否跨環(huán)境了,再比如通過線程名可以快速幫助我們理解異步上下文。
單擊某個(gè) Span,Span 詳情會(huì)以抽屜方式展示,上面是 Span 的摘要信息,下面按照屬性含義做了分類。部分屬性支持跳轉(zhuǎn)到其他平臺(tái),比如 CMDB 和容器平臺(tái),在 Span 詳情頁的打通了指標(biāo)和日志,日志主要根據(jù) TraceID 關(guān)聯(lián)。

指標(biāo)可顯示當(dāng)前 Span 的黃金三指標(biāo)、以及當(dāng)前 Span 所在 JVM 狀態(tài)包括 GC、線程池和 POD 的 CPU 和內(nèi)存以及 POD 所在宿主機(jī)的資源使用情況,這樣可以減少頁面來回切換。
在報(bào)警分析上,主要使用 Prometheus 作為數(shù)據(jù)源,通過專家經(jīng)驗(yàn)梳理告警模板,可以快速的應(yīng)用到其他服務(wù),同時(shí)可以保障新應(yīng)用上線后低成本接入,目前共提供 50 多個(gè)模版。

在告警規(guī)則上,支持同比、環(huán)比、無數(shù)據(jù)。在通知組上支持飛書、短信、電話,以及支持分鐘級(jí)、小時(shí)級(jí)、天級(jí)的告警聚合通知。
往期推薦
-
原來懂Kubernetes,找工作這么吃香! -
小孩也能學(xué)會(huì)的 Kubernetes 繪本教程
-
優(yōu)秀的 Shell 運(yùn)維腳本鑒賞
-
企業(yè)主流全鏈路監(jiān)控系統(tǒng) -
阿里 Nacos 高可用集群部署 -
神器 Nginx 的學(xué)習(xí)手冊 ( 建議收藏 ) -
K8S 常用資源 YAML 詳解 -
DevOps與CI/CD常見面試問題匯總
-
我會(huì)在Docker容器中抓包了! -
19 個(gè) K8S集群常見問題總結(jié),建議收藏 -
運(yùn)維高可用架構(gòu)的 6 大常規(guī)方案
-
運(yùn)維監(jiān)控指標(biāo)全方面總結(jié) -
9 個(gè)實(shí)用 Shell 腳本,建議收藏!
-
詳解 K8S Helm CI/CD發(fā)布流程
-
ES+Redis+MySQL,這套高可用架構(gòu)設(shè)計(jì)太頂了! -
一臺(tái)服務(wù)器最大能支持多少條TCP連接? -
K8S運(yùn)維必知必會(huì)的 Kubectl 命令總結(jié)
-
16 張圖硬核講解 Kubernetes 網(wǎng)絡(luò)
-
史上最全 Jenkins Pipeline流水線詳解 -
主流監(jiān)控系統(tǒng) Prometheus 學(xué)習(xí)指南
點(diǎn)亮,服務(wù)器三年不宕機(jī)

