![]()
作者 | Steef-Jan Wiggers
譯者 | 馬可薇
Discord 工程團隊分享了他們是如何在支撐數百萬并發用戶的情況下,為自家的 Elixir 基礎設施加入分布式追蹤的。他們做了一個自定義的 “Transport” 庫,把追蹤上下文包在 Elixir 的消息傳遞機制外面,從而解決了在 actor 架構里做可觀測性埋點的一個核心難題。
和基于 HTTP 的微服務不同(trace context 通常放在 header 里傳遞),Elixir 的 actor 模型是在進程之間直接傳任意消息,本身并沒有元數據這一層。Discord 希望在整個聊天系統里實現端到端的可觀測性,但遇到了一個問題:OpenTelemetry 的標準追蹤 只能在單個服務內部生效,沒法在 Elixir 進程之間傳遞上下文。
團隊總結了三個必須滿足的要求:一是對開發者足夠友好,方便落地;二是既支持原始消息,也支持 GenServer 抽象;三是能夠在生產環境實現無停機部署。
Discord 的方案引入了一個叫 “Envelope(信封)” 的基礎結構,用來把 trace context 包進消息里。實現看起來非常簡單,本質上就是一個結構體,里面包含原始消息和序列化后的 trace carrier:
end這個庫提供了可以直接替換的 GenServer call 和 cast 方法,會自動把發出去的消息包一層。在接收端,通過一個 handle_message 函數統一處理舊的裸消息和新的 Envelope 消息:如果有 trace context 就提取出來,用完之后再清理掉。
這個“統一處理”的設計在上線過程中非常關鍵。Discord 不可能一夜之間改掉所有消息傳遞邏輯,也沒法同時更新所有節點。這個庫可以同時處理已埋點和未埋點的消息,從而支持逐步遷移,而且不需要重啟服務。
Discord 的架構在擴展性上有一些獨特挑戰。比如一個用戶在一個有一百萬在線成員的服務器里發消息,這一個帶追蹤的操作就可能生成一百萬個子 span——每個會話一個,用來把消息轉發給客戶端。
團隊基于 fanout(消息擴散規模)做了動態采樣。發給單個用戶的消息,100% 保留采樣結果。發給 100 個用戶時,采樣率降到 10%。當接收人數超過 1 萬時,只有 0.1% 的會話會記錄會采樣。這樣既能保留有價值的追蹤數據,又不會把可觀測性系統壓垮。
![]()
來源:Discord 博客
最初上線時,追蹤帶來的開銷超出了 Discord 的預期。那些最活躍、擁有數百萬成員的服務器,一度跟不上消息流量。性能分析發現,即使 99% 以上的操作沒有被采樣,進程仍然花了大量時間在解析 trace context 上。
解決方案是:只對被采樣的請求傳遞 trace context。未采樣的請求在 Envelope 里就不帶 context,從而省掉序列化和解析的開銷。這對傳統的 head sample 語義做了一點小改動,但成功消除了 CPU 峰值問題。
第二個優化針對 sessions 服務:在 fanout 過程中記錄 span 會讓 CPU 使用率提高 10 個百分點。Discord 選擇禁止 sessions 在接收到 fanout 消息后再開啟新的 trace。它們可以繼續已有的 trace,但不會自己決定是否采樣。這一改動幾乎消除了所有額外開銷,把 CPU 使用率從 55% 降到 45%。
最顯著的一次優化來自對 gRPC 請求處理的分析。在 Elixir 服務和 Discord 的 Python API 交互時,有 75% 的請求處理時間都花在解析 trace context 上。團隊為此做了一個過濾器,可以直接從編碼后的 trace context 字符串里讀取采樣標志,而不需要完整反序列化。如果沒有被采樣,就完全不傳 context。
這套投入在最近一次故障中發揮了作用,當時某個服務器跟不上用戶的活動。追蹤數據顯示,用戶連接該服務器進程時出現了長達 16 分鐘的延遲——這是一個指標和日志都很難直接看出來的用戶影響。追蹤還揭示了下游的連鎖反應:故障期間用戶甚至無法點擊進入這個服務器。
Discord 工程師 Nick Krichevsky 表示,這種嚴重性能下降雖然很少見,但分布式追蹤已經成為排查問題的關鍵手段——很多問題“以前根本無從下手”。
Transport 這個庫代表了一種在 actor 系統中實現分布式追蹤的務實做法。它不是強行套用 HTTP 那種 metadata 模式,而是直接包裹 Elixir 的消息傳遞機制,讓 Discord 在保持原有架構優勢的同時,也獲得了可以支撐生產規模的可觀測性。
聲明:本文為 InfoQ 翻譯,未經許可禁止轉載。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.