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

如何排查IIS托管.NET 4.5.2 SPA应用的突发内存泄漏问题

问题排查与定位建议

首先纠正一个核心认知偏差:存储过程变更完全可能引发IIS工作进程内存暴涨,并非只会占用SQL Server侧内存,结合你提到的问题出现时间点和数据库存储过程调整时间完全吻合,这部分是最高优先级排查项,不要先排除。

  • 优先核查近1个月调整过的所有存储过程,重点排查两类问题:
    • 是否存在漏写关联条件导致的笛卡尔积、去掉分页/Top限制、过滤条件逻辑写反的问题,这类错误会让查询返回远超预期的结果集(从正常的几十行变成几十万、上百万行),.NET端的数据访问层不管是用DataTable还是ORM实体接收,都会把全量结果加载到w3wp进程内存中,2分钟内存冲到数GB是非常典型的表现。
    • 是否新增了无分页返回大字段(如NVARCHAR(MAX)类型存储的文本、二进制数据、长历史备注)的逻辑。
  • 这个排查方向完全匹配你观察到的所有现象:
    • 每日复发、持续15分钟后全天正常:大概率是每日凌晨SQL Server自动刷写缓存、重编译执行计划,早高峰第一批用户触发该低效查询,大量并发请求同时拉取超量数据直接打满内存;等15分钟后SQL重新生成了命中索引的执行计划、或者相关查询结果被缓存,后续请求的返回数据量回归正常,内存自然稳定。
    • 迁移IIS服务器后问题复现、测试环境无法复现:问题根源在数据库侧,更换Web服务器当然不会解决;测试环境的数据量、数据分布和生产差异极大,根本触发不了全表扫描、大结果集返回的问题。
    • IIS日志、系统事件日志无异常:这类请求本身会返回200状态码,默认IIS日志不记录响应体大小、返回数据量指标,你看不到异常是正常的。

补全之前排查的遗漏操作,不要贸然升级依赖

你提到不愿无理由升级依赖类库的判断是完全正确的,这类无代码变更、固定周期触发的问题和第三方依赖版本几乎没有关联,盲目升级只会引入额外故障,先做以下排查:

  • 调整内存转储抓取时机:之前用WinDbg分析没拿到有效信息,大概率是抓dump的时间不对——不要等内存涨满触发AppPool回收了再抓,要在内存刚开始快速上涨的30秒内抓取全量dump,抓完加载SOS调试扩展,执行!dumpheap -stat查看占用内存最高的对象类型,90%以上的概率会看到String、DataRow、实体类对象占了80%以上的内存,顺着对象引用链就能定位到是哪个接口、哪个SQL请求加载的这些数据。
  • 开启IIS日志的扩展字段:给日志加上sc-bytes(响应体大小)、time-taken(请求耗时)字段,问题触发时段筛选出响应体超过10MB、耗时超过10秒的请求,基本可以直接定位到异常接口。
  • 用性能监视器实时观测:在问题高发时段给w3wp进程添加.NET CLR Memory分类下的Allocated Bytes/sec计数器,如果观测到内存暴涨阶段每秒内存分配速率达到数百MB,就可以确定是请求处理过程中加载了超量数据,和后台线程、缓存泄漏类问题无关。
  • 数据库侧开慢查询追踪:开启SQL Server的扩展事件追踪,抓取执行时长超过3秒的查询,问题触发时段的慢查询列表里,那个返回数据量最大、执行频率最高的查询,基本就是改坏的存储过程。

临时止血方案

  • 配置AppPool在每日业务低峰期(比如凌晨5点)做一次固定时间回收,避免内存打满后的被动回收,减少旧进程长时间不退出占用内存的问题。
  • 如果查到对应异常存储过程,临时给相关接口加返回行数限制,先避免内存打满触发回收,再慢慢优化存储过程逻辑、补全索引。

补充说明:你观察到的旧工作进程需要5分钟才能完全终止、终止前内存冲到8GB的现象,完全符合大结果集慢查询的特征:IIS触发AppPool回收时,会等待正在执行的请求处理完成(默认等待时长通常配置为90秒到5分钟不等),这些正在等待SQL返回大结果集的请求不会被立刻终止,占用的内存也不会被释放,才会出现进程退出前内存持续冲高的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:39:19