You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一进程多Web应用运行时OpenTelemetry Span ID重复问题解决

同一进程多WebApplication的OpenTelemetry追踪隔离方案

问题背景

同一进程内运行两个监听不同端口的独立WebApplication(服务名分别为GATEWAY和SUBSCRIPTIONS),各自配置OpenTelemetry时使用了以下代码:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracerProviderBuilder =>
            tracerProviderBuilder
                .ConfigureResource(cfg =>
                {
                    cfg.AddService(serviceName);
                })
                .AddAspNetCoreInstrumentation()
                .AddHttpClientInstrumentation()
                .AddGrpcClientInstrumentation()
                .AddSource("GraphQL")
                .AddSource(GraphQLTelemetryProvider.SourceName)
                .AddSource(DiagnosticHeaders.DefaultListenerName)
                .AddSentry()
                .AddOtlpExporter(options =>
                {
                    options.Endpoint = new Uri("http://localhost:4317");
                })
    );

实际运行出现以下问题:

  • Jaeger中追踪数据重复:GATEWAY收到请求后发起的外部请求,Jaeger同时显示GATEWAY和SUBSCRIPTIONS的入站请求,且出站请求全部归属GATEWAY
  • 日志中大量出现duplicate span IDs; skipping clock skew adjustment警告,不同服务的Span被重复记录

根本原因

同一进程内默认共享了OpenTelemetry的TracerProvider和DiagnosticListener实例,导致两个WebApplication的 instrumentation 会监听相同的诊断事件,进而重复采集Span,引发Span ID冲突。

解决方案

为每个WebApplication创建完全独立的OpenTelemetry配置,包括独立的服务集合、TracerProvider和Instrumentation实例,避免资源共享。

1. 拆分服务配置,独立构建WebApplication

不要在共享容器中配置OTEL,分别为两个服务创建专属的WebApplicationBuilder,各自配置OTEL:

GATEWAY服务配置示例

// 为GATEWAY创建独立的构建器
var gatewayBuilder = WebApplication.CreateBuilder(args);
gatewayBuilder.Services.AddOpenTelemetry()
    .WithTracing(tracerProviderBuilder =>
        tracerProviderBuilder
            .ConfigureResource(cfg => cfg.AddService("GATEWAY"))
            // 关键:通过端口筛选只追踪GATEWAY的请求
            .AddAspNetCoreInstrumentation(options =>
            {
                options.Filter = context => context.Request.Host.Port == 5000; // 替换为GATEWAY实际监听端口
            })
            .AddHttpClientInstrumentation()
            .AddGrpcClientInstrumentation()
            .AddSource("GraphQL")
            .AddSource(GraphQLTelemetryProvider.SourceName)
            .AddSource(DiagnosticHeaders.DefaultListenerName)
            .AddSentry()
            .AddOtlpExporter(options =>
            {
                options.Endpoint = new Uri("http://localhost:4317");
            })
    );

// 配置GATEWAY的路由、中间件等逻辑
var gatewayApp = gatewayBuilder.Build();
// ... 此处添加GATEWAY的业务配置
gatewayApp.Run("http://localhost:5000");

SUBSCRIPTIONS服务配置示例

// 为SUBSCRIPTIONS创建独立的构建器
var subscriptionsBuilder = WebApplication.CreateBuilder(args);
subscriptionsBuilder.Services.AddOpenTelemetry()
    .WithTracing(tracerProviderBuilder =>
        tracerProviderBuilder
            .ConfigureResource(cfg => cfg.AddService("SUBSCRIPTIONS"))
            // 关键:通过端口筛选只追踪SUBSCRIPTIONS的请求
            .AddAspNetCoreInstrumentation(options =>
            {
                options.Filter = context => context.Request.Host.Port == 5001; // 替换为SUBSCRIPTIONS实际监听端口
            })
            .AddHttpClientInstrumentation()
            .AddGrpcClientInstrumentation()
            .AddSource("GraphQL")
            .AddSource(GraphQLTelemetryProvider.SourceName)
            .AddSource(DiagnosticHeaders.DefaultListenerName)
            .AddSentry()
            .AddOtlpExporter(options =>
            {
                options.Endpoint = new Uri("http://localhost:4317");
            })
    );

// 配置SUBSCRIPTIONS的路由、中间件等逻辑
var subscriptionsApp = subscriptionsBuilder.Build();
// ... 此处添加SUBSCRIPTIONS的业务配置
subscriptionsApp.Run("http://localhost:5001");

2. 额外优化(可选)

如果仍存在跨服务事件监听问题,可以:

  • 为每个服务添加唯一的自定义SourceName,避免共享Source导致的事件交叉
  • 对HttpClient/GrpcClient Instrumentation也添加筛选逻辑,确保出站请求归属正确服务

3. 验证效果

启动两个服务后,分别发起请求,检查Jaeger:

  • 各服务的请求只显示对应服务名的Span
  • 不再出现duplicate span IDs警告

核心总结

  • 必须为每个WebApplication独立配置OpenTelemetry,禁止共享服务容器中的OTEL资源
  • 通过AspNetCore Instrumentation的Filter选项精准过滤当前服务的请求,防止跨服务采集
  • 确保每个服务拥有独立的TracerProvider实例,从根源上隔离追踪数据

内容的提问来源于stack exchange,提问作者user606521

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:11:09