Observability:深度聊聊採樣 Sampling 場景和落地案例 - 上篇
採樣的知識背景
回顧可觀測系統解決的主要問題
系統的調用鏈信息 Traces、Metrics、Logs 串聯後,開發者基於調用鏈進行行爲分析。
常見的使用場景可以分爲以下幾類:
異常檢測
異常檢測指的是定位和排查一些引發系統異常行爲的請求,通常這些請求的出現頻率很低。儘管異常事件被採樣的概率很低,但它的信息熵大,能給到開發者更多細節信息。這些細節可能體現在:慢請求、慢查詢、循環調用未設上限、存在錯誤級別日誌、未覆蓋測試的問題邏輯分支等等。如果調用鏈追蹤系統能主動爲開發者發現異常問題,將使得風險隱患提前暴露,並被扼殺在搖籃中。
健康度分析
健康度分析指的是分析業務系統健康度,分析粒度可能包括單個接口、單個服務、多個服務等等;分析範圍可能是單個請求或多個請求;分析角度可能包括埋點指標、依賴關係、流量大小等等。分析反映系統主要流程的健康狀態,一些配置的改動,如存儲節點修改、客戶端日誌上報頻率,都可能反饋到系統穩態。健康度關鍵點:
可用性
首先,將業務系統的運行狀態分爲 “可用” 和“不可用”兩個狀態。若業務系統或其支撐服務不可用,則健康度直接 0 分甚至負分。
其次,業務系統關聯的網絡、中間件、數據庫的運維狀態分爲 “可用” 和“不可用”兩個狀態。如存在 “不可用” 狀態,則根據關鍵點重要等級權重計算業務系統健康度。
再次,業務系統底層的硬件設備,也存在 “可用” 和“不可用”兩個狀態,考慮到當前服務均使用高可用模式,所以會存在服務 “可用” 但支持的硬件出現 “不可用” 情況。
性能
性能指標更關注於業務系統,包含:響應時間,可以再細分到:響應時間(宏觀);加載速度(微觀,各個服務),可以通過控制性能健康度權重值調節業務系統健康度。
穩態性能分析:定位和排查系統穩態中的性能問題,這些問題的起因通常與異常檢測類似,只是其影響尚不足以觸發報警。
服務依賴分析:構建接口級別的依賴關係圖,節點通常爲接口或服務,邊通常爲接口或服務的調用關係,邊的權重則爲流量。構建方式可以分爲離線構建和在線構建,對應的就是靜態關係圖和動態關係圖。這些信息可以以基礎 API 的方式提供給上游應用使用,如 APM。
資源歸因
資源歸因解答的主要問題是:“誰該爲我的服務成本買單?” 它需要將資源消耗或佔用與請求方關聯,資源歸因也是成本分析的基礎。
負載建模
負載建模主要指分析和推測系統的行爲表現,該場景解答的問題通常可以表述爲 “如果出現 XX 變化,系統整體或關鍵鏈路狀態會發生什麼改變?” 常見應用如容量預估、全鏈路壓測、混沌測試等等。
採樣角色在調用鏈系統架構的位置
從調用鏈系統架構設計看,採樣處理幾乎每個階段都在。
調用鏈常見架構設計
採樣
採樣分成兩種部署模式:客戶端採樣、服務端採樣,有的系統客戶端、服務器同時採樣。
實踐中無論從計算和存儲資源成本消耗上分析,還是從具體使用場景出發,都不一定需要收集所有埋點數據。因此許多調用鏈追蹤系統會要求按照一定的策略上報數據,目的是取得成本與收益之間的平衡,提高投入產出比。
上報
數據可以從服務實例中直接發送到處理中心,或經由同一宿主機上的 agent 代理上報。使用 agent 上報的好處之一在於一些計算操作可以在 agent 中統一處理,一些邏輯如壓縮、過濾、配置變更等可以集中到 agent 中實現,服務只需要實現很薄的一層埋點、採樣邏輯即可,這也能使得調用鏈追蹤方案對業務服務本身的影響降到最低;使用 agent 上報的另一好處是數據處理服務的發現機制對服務本身透明。因此在每臺宿主機上部署 agent 是許多調用鏈追蹤系統的推薦部署方案。
Kubernetes,Istio 上報也是類似 Agent 原理:SideCar、DaemonSet 的模式,思路類似。
收集中心
調用鏈數據上報到中心節點,通常稱後者爲收集器 (Collector),由收集器完成必要的後處理,如數據過濾、數據標記、尾部採樣、數據建模等等,最後批量寫到不同的存儲服務中,並建立必要的索引。
存儲 / 索引、可擴展性
調用鏈追蹤系統需要處理的數據與全站的請求總量正相關。假如全站所有請求平均要經過 10 個服務處理,那麼調用鏈追蹤系統將需要承擔全站請求總量 10 倍壓力,如果不做任何採樣,一方面系統存儲壓力成指數增長,服務器成本非常高。另一方面鏈路系統其架構設計上要求具備可擴展性。
從架構設計看,採樣在每個階段都有它的影子
採樣的常見場景
A、分佈式系統,微服務系統存在調用鏈比較深情況,讓一個 Trace 產生指數的比例 Span,鏈路數據量巨大。
B、服務 TPS 很高,高併發的情況,全量採集給公司系統整體帶來兩方面壓力:
1、因數據上報造成的每個業務服務的網絡 I/O 壓力
2、因數據採集、分析造成的調用鏈追蹤服務的計算和存儲壓力。
採樣主要爲了幹三件事:
1、節約服務器資源,數據存儲成本
2、高併發帶來鏈路採集的性能瓶頸,講請求量指數級降低可以指數級減少性能問題困難度。
3、異常檢測、鏈路故障排查更聚焦,採樣不只是減小傳送,有可能甚至增加採樣樣本
採樣的好處
這裏,我舉兩個案例給大家一個參考,說實在,這也只是我平時隨便留意的一小部分。接下來下篇,我會總結下他們深層次的原因
伴魚案例
2020 年,我們不斷收到業務研發的反饋:能不能全量採集 trace?這促使我們開始重新思考如何改進調用鏈追蹤系統。我們做了一個簡單的容量預估:目前 Jaeger 每天寫入 ES 的數據量接近 100GB / 天,如果要全量採集 trace 數據,保守假設平均每個 HTTP API 服務的總 QPS 爲 100,那麼完整存下全量數據需要 10TB / 天;樂觀假設 100 名服務器研發每人每天查看 1 條 trace,每條 trace 的平均大小爲 1KB,則整體信噪比千萬分之一。可以看出,這件事情本身的 ROI 很低,考慮到未來業務會持續增長,存儲這些數據的價值也會繼續降低,因此全量採集的方案被放棄。退一步想:全量採集真的是本質需求嗎?實際上並非如此,我們想要的其實是「有意思」的 trace 全採,「沒意思」的 trace 不採。
貨拉拉
2.0 架構雖然能滿足高吞吐量,但是也存在存儲成本浪費的問題。其實從實踐經驗看,我們會發現 80~90% 的 Trace 數據都是無價值的、無意義的數據,或者說是用戶不關心的。那麼用戶關心哪些數據呢?關心鏈路中錯、慢的請求以及部分核心服務的請求。那麼我們是不是可以通過某些方式,把這些有價值的數據給過濾採樣出來從而降低整體存儲成本?在這個背景下,我們進行 3.0 的改造,實現了差異化的完成鏈路採樣,保證 1H 以內的數據全量保存,我定義它爲熱數據,而一小時以外的數據,只保留錯、慢、核心服務請求 Trace,定義爲冷數據,這樣就將整體的存儲成本降低了 60%。
https://www.sohu.com/a/531709613_411876
字節跳動
由於字節整體線上流量非常大,微服務數目衆多,不同微服務的性能敏感度、成本敏感度和數據需求各有不同,例如有些服務涉及敏感數據,必須有非常完整的追蹤數據;有些服務性能高度敏感,需要優先控制採樣數最小化 Overhead;測試泳道、小流量灰度或者線上問題追查等場景會需要不同的採樣策略;常規流量和發生異常的流量也需要不同的採樣策略。
https://blog.csdn.net/ByteDanceTech/article/details/122076591
採樣的主要方案
大致分三類
-
• 頭部連貫採樣:
Head-based coherent sampling
從圖中,採樣決策 Sampling decision 從請求一開始做出了哪些初始節點需要採樣的決定。頭部採樣是沒有做預判的邏輯,從一開始選擇性採集少量數據。但是,如果錯誤發生在沒采集的節點,它無法採集到異常鏈路。 -
• 單元採樣:
Unitary sampling
-
• 尾部連貫採樣:
Tail-based coherent sampling
尾部採樣,是 Agent 在採集完整個服務鏈路,準備將採集數據上報時,根據一定的策略做選擇性上報。比如下面的過程。
- 某個請求出問題開發者需要查看完整調用鏈信息,因此需要連貫採樣。又由於問題請求的發生是小概率事件,只能通過尾部連貫採樣來保證數據都能被捕獲。
一般,業界場景普遍選擇,以尾部採樣爲主,頭部採樣爲輔混合模式。
主流開源和商業系統的採樣實現
SkyWalking
它採樣機制主要在 Agent 端支持 Head-based Sampling:
能夠支持簡單的採樣百分比 Sampling Rate,允許 forceSampleErrorSegment:錯誤鏈路強制採樣。
Skywalking 做了 Slow SQL Sampling:
分佈式系統中,數據庫非常常用,往往也是性能問題常出的中間件。對 SQL 慢查詢的採樣在鏈路調用中一個重要的點,Skywalking 也做了支持
https://skywalking.apache.org/docs/main/v8.5.0/en/setup/backend/slow-db-statement/
Jaeger
採樣策略: 頭部連貫採樣,目前 Jaeger 支持三種採樣方式:
-
• Const:要麼全採樣,要麼不採樣
-
• Probabilistic:按固定概率採樣
-
• Rate Limiting:限流採樣,即保證每個進程每隔一段時間最多采 k 個
除了 Agent 配置外,Jaeger 還支持遠程動態調整採樣方式,但調整的選擇範圍仍然必須爲上面三種之一。爲了防止一些調用量小的請求因爲出現概率低而無法獲得調用鏈信息,Jaeger 團隊也提出了適應性採樣 (Adaptive Sampling) ,但這個提議從 2017 年至今仍然未有推進。
限流採樣適用範圍有限,比如伴魚案例:
伴魚的生產環境中使用的是限流採樣策略:每個進程每秒最多采 1 條 trace。這種策略雖然很節省資源,但其缺點在一次次線上問題排查中逐漸暴露:一個進程中包含多個接口:不論按固定概率採樣還是限流採樣,都會導致小流量接口一直採集不到調用鏈數據而餓死 (starving) 線上服務出錯是小概率事件,導致出錯的請求被採中的概率更小,就導致採到的調用鏈信息量不大,引發問題的調用鏈卻丟失問題
文章出處
https://tech.ipalfish.com/blog/2021/03/04/implementing-tail-based-sampling/
OpenTelemetry
OpenTelemetry 收集器引入尾部連貫採樣的支持。
https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor
OpenTelemetry 尾部連貫採樣提供的策略也是非常豐富,下面常用一些策略
A、常見的百分比採樣
Latency
: Sample based on the duration of the trace.
B、基於 Metric 指標範圍的採樣過濾:在你只想採集一些超過監控閾值的異常鏈路時候很有用
numeric_attribute
: Sample based on number attributes
probabilistic
: Sample a percentage of traces. Read a comparison with the Probabilistic Sampling Processor.
C、專門提供給 API 狀態碼定義採樣,這個場景:異常特殊採樣
status_code
: Sample based upon the status code (OK, ERROR or UNSET)
基於標籤匹配的採樣過濾,這個場景:URL 採樣過濾,某些特定自定義監控採樣過濾,非常靈活,
D、給專門的應用服務和節點打標籤的採樣:很多業務監控會用上
string_attribute
: Sample based on string attributes value matches, both exact and regex value matches are supported
rate_limiting
: Sample based on rate
E、限流採樣: 不詳細說了
OpenTelemetry 還支持多種採樣規則混合搭配方式:它把一種策略叫做Policy
。
你可以根據自身系統,定製化一套完整的採樣方案。
比如下面,是 Collector 收集中心定義的一套完整的採集方案:
processors:
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 10
policies:
[
{
name: test-policy-2,
type: latency,
latency: {threshold_ms: 5000}
},
{
name: test-policy-3,
type: numeric_attribute,
numeric_attribute: {key: key1, min_value: 50, max_value: 100}
},
{
name: test-policy-4,
type: probabilistic,
probabilistic: {sampling_percentage: 10}
},
{
name: test-policy-5,
type: status_code,
status_code: {status_codes: [ERROR, UNSET]}
},
{
name: test-policy-6,
type: string_attribute,
string_attribute: {key: key2, values: [value1, value2]}
},
{
name: test-policy-7,
type: string_attribute,
string_attribute: {key: key2, values: [value1, val*], enabled_regex_matching: true, cache_max_size: 10}
}
]
OpenTelemetry 尾部採樣實例
接下來看一個簡單異常鏈路採集的例子:Github 我放上了案例,大家可以自行下載體驗
https://github.com/laziobird/otel-collector-java/
我們看看對於的效果,在沒有開啓異常採樣前:
所有鏈路都採集上報到 Jaeger 做鏈路數據分析
當我們開啓了一個採集策略配置,對應 otel-collector-config.yaml
簡單配置一個Policy
processors:
batch:
tail_sampling:
policies:
[
{
name: test-policy-5,
type: status_code,
status_code: {status_codes: [ERROR]}
}
]
service:
extensions: [pprof,health_check]
pipelines:
traces:
receivers: [otlp]
processors: [tail_sampling]
exporters: [jaeger]
看看加了異常 Sampling 結果。看到了吧,只有異常鏈路被上報了!
Datadog
默認 Agent 也有頭部採樣,同時支持尾部採樣
Datadog 做全鏈路追蹤的可觀測,同時支持了 RUM、APM 前後端的採樣。
https://docs.datadoghq.com/tracing/trace_ingestion/mechanisms/?tab=environmentvariables#head-based-sampling
在 APM 側,做了基於 Tag 尾部採樣
https://docs.datadoghq.com/serverless/distributed_tracing/
Tail-based sampling and fully customizable tag-based retention filters.
它做了一個採樣 Trace 的權重等級,通過權重區分採樣還是不採樣。
PRIORITY SAMPLING
The sampler can set the priority to the following values:
Datadog::Tracing::Sampling::Ext::Priority::AUTO_REJECT: the sampler automatically decided to reject the trace.
Datadog::Tracing::Sampling::Ext::Priority::AUTO_KEEP: the sampler automatically decided to keep the trace.
染色採樣
剛纔根據權重採樣,是採樣一種常見模式,我們可以歸類染色採樣的範疇:
當我們針對特殊場景、服務進行鍼對性分析時,可以給他們打上特殊標籤 Tag 進行全量採集。
我們簡單看看染色採樣的案例:
騰訊雲的自定義採樣,
內容出處:
https://cloud.tencent.com/document/product/1463/66104
採樣模式的案例分享和簡單講解
尾部連貫採樣 VS 頭部連貫採樣
收錢吧一開始頭部連貫採樣,後面也是考慮尾部採樣
由於我們目前採樣的是頭採樣(Head-Based Sampling)方案,一旦在鏈路中間的服務發生拋出異常且這條鏈路沒有被採樣,那麼就會出現有錯誤日誌和報警,但鏈路追蹤系統無法查詢到這條鏈路的情況,這給開發排查問題帶來很大的阻礙。伴魚最早採用 Jaeger,默認頭部連貫採樣的限流採樣,後面開始使用 OpenTelemetry 一個原因,也是採樣支持尾部採樣
伴魚
伴魚的生產環境中使用的是限流採樣策略:每個進程每秒最多采 1 條 trace。這種策略雖然很節省資源,但其缺點在一次次線上問題排查中逐漸暴露:一個進程中包含多個接口:不論按固定概率採樣還是限流採樣,都會導致小流量接口一直採集不到調用鏈數據而餓死 (starving) 線上服務出錯是小概率事件,導致出錯的請求被採中的概率更小,就導致採到的調用鏈信息量不大,引發問題的調用鏈卻丟失的問題
字節跳動、貨拉拉,OpenTelemetry 都有分享尾部採樣案例,這裏我不一一列舉了。最後,還推薦 Oy LM Ericsson Ab 芬蘭公司 (母公司愛立信)的核心開發 G KIBRIA SHUVO 分享尾部連貫採樣的完整一本書介紹,裏面也有 OpenTelemetry 在尾部採樣的應用實現。
Tail Based Sampling Framework for Distributed Tracing Using Stream Processing
英文原版下載鏈接
https://kth.diva-portal.org/smash/get/diva2:1621787/FULLTEXT01.pdf
作者介紹
蔣志偉,愛好技術的架構師,先後就職於阿里、Qunar、美團,前 pmcaffCTO,目前 Opentelemetry 中國社區發起人,https://github.com/open-telemetry/docs-cn 核心維護者
- • 歡迎關注我們的 Github 項目
https://github.com/open-telemetry/docs-cn
歡迎大家關注 “Opentelemetry” 公衆號,這是中國區唯一官方技術公衆號
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/tnYUOHJT0TOh4iYBHlP4aA