CodeGym /課程 /C# SELF /分散式追蹤與遙測

分散式追蹤與遙測

C# SELF
等級 64 , 課堂 4
開放

1. 介紹

在現代的服務導向架構 (SOA)、微服務和雲端解決方案中,一個使用者請求可能會「飛過」數十個不同的服務才回傳結果。每個節點都會寫各自的日誌,但怎麼知道某處的錯誤或延遲真的和這個特定請求有關?

分散式追蹤 就像物流裡的包裹追蹤系統:你可以看到包裹經過哪些站點、在哪裡被耽擱、哪裡發生了意外。在程式世界裡——它讓你追蹤一個請求穿越所有服務的「旅程」,了解每個地方花了多少時間,以及哪裡發生錯誤或延遲。

為什麼需要追蹤?

  • 定位錯誤:如果出問題,你能立刻看到是哪裡:哪個服務、哪個階段,甚至是哪個具體的方法被呼叫。
  • 找出「瓶頸」:追蹤會顯示哪些服務變慢了、在哪個階段損失最多時間。
  • 用戶行為分析:可以了解客戶真實如何使用你的服務,哪些地方值得優先優化。

它如何工作?

每個請求會得到一個唯一的追蹤識別碼(TraceId),這個 id 隨請求在整個服務堆疊中「旅行」:從前端到後端、從 API 到資料庫再回來。每個階段會建立「spans」,記錄操作的執行時間和額外事件。最終你會得到一棵(或一個圖)操作的樹狀結構,包含各自的持續時間和相互關係。

分散式追蹤的關鍵實體與術語

術語 說明
追蹤 (Trace) 一個請求穿越多個服務的邏輯路徑。由 TraceId 唯一標識。
Span 在追蹤中的一個操作或子操作。每個 span 有自己唯一的識別碼。
TraceId 整個追蹤(整個請求)的唯一識別碼。
SpanId 當前 span(操作)的唯一識別碼。
Parent SpanId 父 span 的 Id(如果這個 span 是另一個操作的一部分)。
Attributes span 的一組自訂元資料:方法名稱、參數、狀態等。
Events/Logs 與 span 關聯的重要事件(例如錯誤、完成)。
Context Propagation 在服務與執行緒之間傳遞追蹤資訊的機制。

2. OpenTelemetry:觀測性的開放標準

簡介 OpenTelemetry

OpenTelemetry 是一套用來從各種應用收集遙測(追蹤、指標、日誌)的開放標準與工具集合。它由 Cloud Native Computing Foundation (CNCF) 支持,已成為雲端與分散式應用領域的事實標準。

OpenTelemetry(簡稱 OTel)能做到:

  • 自動收集並送出追蹤、指標和日誌;
  • 支援主流程式語言,包括 C#, Java, Python 等;
  • 將資料回傳到觀測系統——Jaeger、Zipkin、Azure Monitor、Grafana 等;
  • 透過外掛擴展與設定,適配任何技術棧。

為什麼選 OpenTelemetry?

  • 廠商中立:OTel 是標準,而不是某家公司產品。
  • 相容性:支援主要的追蹤格式,容易整合到 APM 系統。
  • 自動化:大部分工作(例如 HTTP 請求的追蹤)可以自動完成,設定成本低。
  • 可擴展性:OTel 在小系統和大系統都表現良好。

OpenTelemetry 架構:簡單解釋

為了不被「層」搞糊塗,我們來視覺化 OTel 中典型的追蹤資料流。

flowchart LR
    subgraph 應用程式
        A[OpenTelemetry SDK]
    end
    A -->|追蹤, 指標, 日誌| B[OpenTelemetry Collector]
    B -->|匯出到| C[Jaeger/Zipkin/Grafana/Azure/Application Insights 等]
  1. OpenTelemetry SDK:直接嵌入你的應用程式(例如透過 .NET 的 NuGet 套件)。
  2. OTel Collector:獨立的集中器服務(常以 Docker container 部署),接收所有應用的 trace 資料並匯出到你指定的目標。
  3. 觀測前端:你看到漂亮圖表、樹狀圖、能過濾與分析追蹤的系統。

3. 在 C#/.NET 上快速啟動追蹤

我們來在教學用的應用加入基礎的分散式追蹤。主要步驟其實很簡單。

安裝 NuGet 套件

dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Console

OpenTelemetry — SDK 的基底實作;
OpenTelemetry.Exporter.Console — 將追蹤匯出到主控台(也可以換成 Jaeger、Zipkin 等)。

最小化的追蹤設定

在檔案 Program.cs(針對主控台應用):

using OpenTelemetry;
using OpenTelemetry.Trace;

class Program
{
    static void Main(string[] args)
    {
        // 設定追蹤
        using var tracerProvider = Sdk.CreateTracerProviderBuilder()
            .AddSource("DemoApp") // 指定來源名稱
            .AddConsoleExporter() // 將追蹤匯出到主控台
            .Build();

        var source = new System.Diagnostics.ActivitySource("DemoApp");

        // 開始一個新的追蹤(根 span)
        using (var activity = source.StartActivity("主操作"))
        {
            DoWork();
        }
    }

    static void DoWork()
    {
        // 一些應用邏輯...
        System.Threading.Thread.Sleep(300);
    }
}

這裡發生了什麼?

  • 建立 tracer provider,註冊來源("DemoApp")並加入主控台匯出器 AddConsoleExporter()
  • 透過 ActivitySource 在程式根部啟動一個新的「activity」(span)。
  • 在內部執行要被追蹤的工作。

結果:

Activity.Id:          0b69e3e97ca5f14d
Activity.Operation:   主操作
Duration: 00:00:00.3001082
...

自動化的 HTTP 與資料庫追蹤

OpenTelemetry 支援 instrumentation —— 對常用函式庫做自動追蹤。像是經由 HttpClient 的呼叫和對資料庫(ADO.NET)的查詢可以在不改你業務碼的情況下被收集。

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
    .AddHttpClientInstrumentation() // HTTP 呼叫
    .AddSqlClientInstrumentation()  // SQL 呼叫(如果你有使用)
    .AddConsoleExporter()
    .Build();

現在透過 HttpClient 的所有呼叫和 SQL 操作會自動出現在追蹤中。

4. 追蹤的視覺化

在主控台輸出只是第一步。要真正發揮價值,還是要用前端 UI 來視覺化。

Jaeger

Jaeger 是最受歡迎的開源追蹤視覺化系統之一。

  1. 部署 Jaeger(例如用 Docker)。
  2. AddConsoleExporter() 換成:
    .AddJaegerExporter(options =>
    {
        options.AgentHost = "localhost";
        options.AgentPort = 6831;
    })
    
  3. 現在所有的追蹤會在 Jaeger UI 顯示——可以用 TraceId 過濾,查看詳細的時間線圖。

完整指南: OpenTelemetry Jaeger Exporter for .NET

5. 有用的細節

方法比較

不使用 OTel 的話你會手動在日誌裡拷貝 TraceId,希望不會忘記把它傳下去,然後在事件分析時痛苦不已。有了 OTel,整個鏈條會自動建立,並能一鍵視覺化。

方法 工作量 可靠性 可擴展性 相容性
手動在日誌中記錄 TraceId 需要持續維護 只限你自己的應用
OpenTelemetry 部署後低 有保障 廣泛(任意語言、技術棧) 與大多數 APM 與日誌系統相容

架構範例

[Web 客戶端] --> [API 服務] --> [授權服務] --> [資料庫服務]

當使用者按下按鈕,請求會通過這些服務。用 OTel 你可以把「線」(TraceId)在每個服務間延續,自動把行為合併成一個追蹤。

  • 在每個服務中 OTel SDK 會自動從 HTTP 標頭辨識 TraceId,並繼續這個鏈路。
  • 結果是你可以打開單一追蹤——看到哪些毫秒被花在哪裡、發生了什麼、哪裡出錯。

在真實專案與面試中的應用

  • 微服務系統與分散式應用(金融科技、電商平台、SaaS 等)。
  • DevOps / SRE:快速定位問題。
  • 提升 SLA 與系統響應性。
  • 進行效能分析與優化。
  • 在面試中展示成熟的工程實踐經驗。

6. 常見錯誤與實作注意事項

忘了傳遞 TraceContext。 如果服務之間沒有傳遞 TraceId(例如忘了把相應的 HTTP 標頭帶上),追蹤會被切斷——呈現成孤立的「點」,觀測的效果就沒了。

未被 instrument 的程式碼。 如果某個函式庫或框架不支援自動 instrument,部分操作會掉出追蹤(但你可以用 ActivitySourceStartActivity() 手動建立 spans)。

資料過剩。 對每個請求都收集追蹤在大流量生產環境中成本很高。通常會只對部分請求開啟(sample rate),或基於觸發器收集(錯誤、慢請求)。

效能影響。 使用非同步匯出時 OTel 對效能的影響很小,但在超大流量下仍要注意 overhead,並調整採樣率。

1
問卷/小測驗
記錄,等級 64,課堂 4
未開放
記錄
Logging、監控還有追蹤
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION