CodeGym /课程 /C# SELF /分布式追踪与遥测

分布式追踪与遥测

C# SELF
第 64 级 , 课程 4
可用

1. 引言

在现代的面向服务架构 (SOA)、微服务和云方案里,一个用户请求可能会在返回结果前“飞过”几十个不同的服务。每个节点都写自己的日志,但怎么知道某个位置的错误或延迟真的是和这个特定请求有关?

分布式追踪 就像物流里的包裹追踪系统:你能看到包裹经过了哪些站点、在哪儿滞留了、哪里出了问题。在编程世界里——它让你能追踪一个请求在所有服务中的“旅行”,知道每段耗时多少、哪里发生了错误或延迟。

为什么需要追踪?

  • 定位错误:出问题时你能马上看到在哪个服务、哪个阶段、甚至是哪个具体方法被调用。
  • 发现“瓶颈”:追踪会显示哪部分服务“慢”,在哪个阶段消耗最多时间。
  • 用户场景分析:可以理解客户真实如何使用你的服务,该把优化投入到哪儿。

它怎么工作?

每个请求会拿到一个唯一的追踪标识(TraceId),这个标识会随着请求在整个服务栈中“旅行”:从前端到后端,从 API 到数据库再回来。每个阶段会创建 span(spans),记录操作的耗时和额外事件。最终你会得到一个操作树(或图),带有每个节点的持续时间和它们之间的关联。

分布式追踪的关键实体与术语

术语 描述
追踪(Trace) 一个请求穿过多个服务的逻辑路径。由唯一的 TraceId 标识。
span(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 容器部署),接收所有应用的 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);
    }
}

这里发生了什么?

  • 创建了追踪提供者,注册了源("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. 追踪的可视化

输出到控制台只是第一步。要真正发挥价值,最好用带可视化的前端。

Jaeger

Jaeger 是最流行的开源追踪可视化系统之一。

  1. 部署 Jaeger(比如用 Docker)。
  2. AddConsoleExporter() 换成:
    .AddJaegerExporter(options =>
    {
        options.AgentHost = "localhost";
        options.AgentPort = 6831;
    })
    
  3. 现在所有追踪都会显示在 Jaeger UI 中——可以按 TraceId 过滤,查看详细的时间线。

完整指南:OpenTelemetry Jaeger Exporter 用于 .NET

5. 有用的细节

方法比较

不使用 OTel 时你得手动把 TraceId 写到日志里,希望别忘了往下传,然后在分析事故时受罪。用 OTel 后整条链自动串起来,一键可视化。

方法 工作量 可靠性 可扩展性 兼容性
手动记录 TraceId 需要持续维护 仅限你的应用
OpenTelemetry 最小化(部署后) 可靠 广泛(任意语言、技术栈) 与大多数 APM 和日志系统兼容

架构示例

[网页客户端] --> [API 服务] --> [授权服务] --> [数据库服务]

当用户点击按钮,请求会通过这些服务。借助 OTel 你可以把那根线(TraceId)从每个服务串起来,自动把各段逻辑合并成一条追踪。

  • 在每个服务里 OTel SDK 会自动从 HTTP header 识别 TraceId 并继续链路。
  • 结果是你可以打开一个追踪——看哪些地方耗了毫秒,发生了什么,哪里出错了。

在真实项目和面试中的应用

  • 微服务系统和分布式应用(金融科技、市场平台、SaaS 等)。
  • DevOps/SRE:快速定位问题。
  • 提升 SLA 和服务响应能力。
  • 性能分析与优化。
  • 面试中展示成熟的工程实践。

6. 常见错误和实现注意点

忘了传递 TraceContext。 如果服务间不传 TraceId(比如忘记把必要的 HTTP header 透传),追踪会被断开——看起来像孤立的“点”,可观测性的好处就没了。

未被 instrument 的代码。 如果某个库或框架不支持自动 instrument,那些操作会从追踪里缺失(不过你可以通过 ActivitySourceStartActivity() 手动创建 span)。

数据过多。 为每个请求采集追踪在大流量下代价很高。通常只对部分请求开启追踪(sample rate),或基于触发条件采集(错误、慢请求等)。

性能影响。 正确使用异步导出时 OTel 对性能的影响很小,但在极大流量下仍需关注开销并调整采样率。

1
调查/小测验
日志记录第 64 级,课程 4
不可用
日志记录
Logging、监控和追踪
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION