.NET API每次请求/登录内存持续暴涨,如何排查?
排查建议:API内存持续增长且GC未回收问题
问题概述
这些API每10秒接收一次Service Worker的请求,Service Worker通过JWT(Identity)登录,随后调用一个端点检查数据库中是否有标记为待发送的新邮件,目前始终返回无结果。该流程每10秒重复一次,且每次都会更新令牌(Worker每次都会重新登录)。
昨晚启动API后,今早内存占用已增至4.5GB且仍在持续增长。查阅资料后多数观点认为“GC最终会回收”,但实际GC并未自动回收,已影响其他服务运行。
使用dotMemory分析仅能看到GC将对象从Heap0移至Heap1和Heap2,但未进行回收。强制GC会将所有对象移至Heap Generation 2,但从未清理。
(附两张示意图:API请求流程示意图、GC堆代际变化趋势图)
具体排查方向
1. 定位Gen2堆中留存的核心对象
- 用dotMemory的对象快照对比功能,间隔10-30分钟拍两次快照,找出持续增长的Top对象类型(比如数据库上下文、JWT认证对象、日志实例、静态集合等)
- 检查这些对象的引用链,确认是否被静态变量、全局缓存、单例实例持有,导致无法被GC回收
2. 检查数据库操作的资源释放
- 确认数据库上下文(DbContext)是否每次请求都用
using包裹,避免因上下文未释放导致的实体对象、连接资源堆积 - 排查邮件查询语句:即使返回无结果,是否存在隐式加载关联数据、创建大量临时查询对象的情况
- 检查数据库连接池配置,是否因连接未正确释放导致连接对象堆积
3. 验证JWT登录流程的泄漏点
- 每次重新登录时,旧的JWT令牌、ClaimsPrincipal、认证票据是否被全局会话存储或静态集合持有未清理
- 检查Identity认证中间件的配置,是否开启了不必要的会话持久化,导致登录生成的对象无法被回收
4. 监控GC的实际行为
- 用
dotnet-counters工具实时监控GC指标:dotnet-counters monitor --process-id <PID> System.Runtime,查看GC触发次数、堆内存变化、Gen2堆大小 - 确认应用的GC模式(工作站/服务器GC),服务器GC在内存充足时会延迟回收,可尝试调整
DOTNET_GC_SERVER=0临时切换为工作站GC验证 - 检查应用是否设置了过大的内存阈值,导致GC触发条件未满足
5. 排查第三方依赖与中间件
- 检查使用的JWT库、Identity组件、邮件客户端是否存在已知的内存泄漏问题,查看官方GitHub Issues或更新日志
- 临时禁用邮件查询逻辑,仅保留登录流程,验证内存是否还增长,定位问题环节
需要补充的关键信息
- API使用的.NET版本、Identity版本、数据库访问框架(EF Core/ADO.NET等)
- dotMemory中Gen2堆占比最高的Top 5对象类型及数量变化
- 服务器的总内存容量、GC模式配置
- 应用的日志中是否有GC相关的警告或错误
内容的提问来源于stack exchange,提问作者Varin
相关产品推荐
相关产品推荐

