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

.NET 6环境下OpenTelemetry指标发送中断及gRPC通信异常问题排查求助

.NET 6环境下OpenTelemetry指标发送中断及gRPC通信异常问题排查求助

大家好,我在基于.NET 6开发的Web应用中使用OpenTelemetry做指标监控,最近遇到了几个棘手的问题,折腾了好一阵还是没彻底解决,想请教下社区的各位大佬有没有相关经验或者排查思路。

初始问题:指标突然停止发送,仅能通过重启应用池恢复

我的技术栈和配置如下:

  • 框架:.NET 6.0
  • 语言:C#
  • OpenTelemetry版本:OpenTelemetry 1.6.0、OpenTelemetry.Exporter.OpenTelemetryProtocol 1.6.0

配置逻辑是在Program.cs中调用builder.Services.AddOpenTelemetry(builder.Configuration),并通过单独的MetricsConfigurator类做具体配置,核心代码片段如下:

private static readonly AsyncLocal<MetricStreamConfiguration> CurrentCallConfiguration = new();

public static MeterProvider Configure(IConfiguration configuration, Assembly mainAssembly)
{
    var appName = mainAssembly.GetName();
    var resource = ResourceBuilder.CreateDefault()
        .AddService(serviceName: appName.Name, serviceVersion: appName.Version!.ToString())
        .AddAttributes(new KeyValuePair<string, object>[]
        {
            new("server.name", Environment.MachineName),
            new("process.id", Environment.ProcessId)
        });

    var exportInterval = TimeSpan.FromMilliseconds(configuration.GetValue("OpenTelemetry:ExportIntervalMilliseconds", 60000));

    return Sdk.CreateMeterProviderBuilder()
        .AddMeter("*")
        .SetResourceBuilder(resource)
        .AddView(instrument =>
        {
            var config = CurrentCallConfiguration.Value;
            CurrentCallConfiguration.Value = null;
            return config;
        })
        .AddOtlpExporter((eo, mo) =>
        {
            eo.Endpoint = new Uri("http://localhost:5110");
            eo.Protocol = OtlpExportProtocol.Grpc;
            mo.PeriodicExportingMetricReaderOptions = new PeriodicExportingMetricReaderOptions
            {
                ExportIntervalMilliseconds = (int)exportInterval.TotalMilliseconds
            };
            mo.TemporalityPreference = MetricReaderTemporalityPreference.Delta;
        }).Build();
}

public static void AddOpenTelemetry(this IServiceCollection services, IConfiguration configuration)
{
    var meterProvider = Configure(configuration, Assembly.GetCallingAssembly());
    services.AddSingleton(meterProvider);
}

public static Meter UsingConfiguration(this Meter meter, MetricStreamConfiguration configuration)
{
    CurrentCallConfiguration.Value = configuration;
    return meter;
}

已尝试的排查步骤

  • 检查应用日志,无相关错误或警告
  • 监控服务器资源使用,未发现异常
  • 将所有OpenTelemetry相关包升级到最新版本
  • 复查配置代码,未发现明显错误或冲突
  • 指标停发时抓取内存dump,发现进程中没有OpenTelemetry实例;重启应用池后实例重新出现,指标恢复发送

尝试解决GC回收问题(更新10/04/2023)

我们推测是GC误将MeterProvider实例判定为无用对象提前回收,导致指标发送中断。于是做了如下调整:
新增静态字段保存MeterProvider实例,并使用GC.KeepAlive防止被回收,替换了之前的services.AddSingleton逻辑:

private static MeterProvider Provider;

// 配置逻辑...

Provider = Sdk.CreateMeterProviderBuilder()
// 配置逻辑...
.Build();

// 更多配置逻辑...

GC.KeepAlive(Provider);

目前这个调整初步有效,但我不确定这是不是最优解——有没有更规范的方式来确保MeterProvider不被GC提前回收?另外也担心长期运行会不会导致内存膨胀?

新问题:gRPC通信异常(更新10/11/2023)

调整配置后部署到AWS测试环境,应用运行约3小时后出现新的错误:

2023-10-10T07:38:24.9429543Z: Exporter failed to send data to collector to {0} endpoint... Grpc.Core.RpcException: Status(StatusCode="Unavailable", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The request was aborted. IOException: The response ended prematurely while waiting for the next frame from the server.", DebugException="System.Net.Http.HttpRequestException: An error occurred while sending the request.")

应用和采集器部署在同一台机器上,网络问题的可能性很低。我们做了这些操作:

  • 先后重启两台Web服务器的应用池,重启后指标发送恢复正常
  • 检查采集器的活跃连接,重启前没有来自应用的进程,重启后出现

这个问题仅在**.NET 6 + IIS进程内托管 + AWS环境**下出现,指标本身采集正常,但和gRPC服务的通信会中断。目前我们在排查是不是采集器端的问题,以及聚焦于IOException中“响应提前结束等待服务器下一帧”的原因。

额外问题:日志写入时的TaskCancellationException

除此之外,还频繁遇到日志写入失败的问题,错误信息如下:

Failed to write logs to OpenTelemetry due to System.Threading.Tasks.TaskCanceledException: Reached deadline.
at Grpc.Core.Channel.d__16.MoveNext() in /path/obfuscated/Grpc.Core/Channel.cs:line 146
... [省略后续栈跟踪]
at Obfuscated.OpenTelemetryLogProvider.d__39.MoveNext() in /path/obfuscated/OpenTelemetryLogProvider.cs:line 250

这个错误出现频率不定,看起来和gRPC通道状态变更的机制有关,导致日志写入延迟或失败,对我们的运维监控影响很大。

求助方向

  1. 针对MeterProvider被GC提前回收的问题,除了静态字段+GC.KeepAlive,有没有更符合.NET最佳实践的解决方案?
  2. 对于同机器部署下出现的gRPC Unavailable错误和TaskCanceledException,有什么具体的排查思路或解决办法?

非常感谢大家的耐心和帮助,期待各位的宝贵建议!

备注:内容来源于stack exchange,提问作者Simone Spagna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 12:12:58