.NET 7.0如何打印完整GC详情?排查K8s服务OOM问题
.NET K8s OOM问题排查:验证GC环境变量与打印GC详情
一、确认.NET是否读取了GC相关环境变量
三种实用验证方法:
- 直接打印环境变量:在应用启动的
Program.cs中添加代码,读取并输出目标GC环境变量到日志,示例:
部署后通过var heapCount = Environment.GetEnvironmentVariable("DOTNET_GC_HEAPCOUNT"); var heapLimit = Environment.GetEnvironmentVariable("DOTNET_GC_HEAPLIMIT"); Console.WriteLine($"DOTNET_GC_HEAPCOUNT: {heapCount}, DOTNET_GC_HEAPLIMIT: {heapLimit}");kubectl logs <pod-name>查看输出,确认变量值是否符合预期。 - 检查容器环境变量注入:在K8s集群中执行命令,直接查看容器内的环境变量:
确认目标GC变量是否存在且值正确,排除K8s配置层面的注入问题。kubectl exec <pod-name> -- printenv | grep DOTNET - 通过dump文件验证GC配置:在容器内安装
dotnet-dump工具,执行dotnet-dump collect生成dump文件,再用dotnet-dump analyze打开,输入eeheap -gc命令,查看Heap Count等参数是否与设置的环境变量一致。
二、打印GC详情(类似Java PrintGCDetails)
.NET提供多种方式输出GC详细日志,助力内存问题排查:
- 通过环境变量开启GC日志:设置
DOTNET_GC_LOGGING环境变量,开启不同级别的GC日志输出:- 基础GC日志:
DOTNET_GC_LOGGING="1",输出GC开始、结束的基本信息 - 详细日志:
DOTNET_GC_LOGGING="gcstart,gcend,gen,size,alloc,promotion",包含GC代、内存大小、分配与晋升情况
日志会直接输出到容器控制台,通过kubectl logs <pod-name>即可查看。
- 基础GC日志:
- 代码中订阅GC事件:在应用中监听GC回收事件,自定义记录日志,示例:
// 记录各代GC回收次数 AppDomain.CurrentDomain.ProcessExit += (s, e) => { for (int i = 0; i <= GC.MaxGeneration; i++) { Console.WriteLine($"GC Generation {i}: {GC.CollectionCount(i)} collections"); } }; // 订阅Full GC通知 GCSettings.RegisterForFullGCNotification(10, 10); Task.Run(async () => { while (true) { var status = GC.WaitForFullGCApproach(); if (status == GCNotificationStatus.Succeeded) { Console.WriteLine("Full GC is approaching"); } await Task.Delay(1000); } }); - 使用dotnet-trace捕获GC事件:在容器内执行命令,指定GC相关事件提供者:
生成的dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:0x2000:5trace.nettrace文件可通过dotnet-trace analyze本地分析,查看GC触发时机、内存变化等详细数据。
额外提示
K8s环境下需注意容器的resources.limits.memory配置,如果该值远低于应用实际内存需求,即使GC参数配置正确,仍会触发OOM Kill。建议先确认容器内存限制是否匹配应用的内存消耗模型。
内容的提问来源于stack exchange,提问作者黄天文
相关产品推荐
相关产品推荐

