作为一个常年跟 .NET 应用在云端环境里“斗智斗勇”的开发者,我太熟悉这个场景了。你高高兴兴把应用部署到 Azure App Service,配置了 4GB 内存,心里想着“这内存管够”。结果跑起来一看,内存占用曲线平平淡淡,始终在 500MB 左右徘徊,CPU 也是忽高忽低。这时候你可能会疑惑:内存没占满,是不是应用没吃饱,性能没榨干?如果你是这么想的,并且试图去优化代码让内存“用满”,那你可能从一开始就跑偏了。
这篇文章就专门聊聊这个现象:.NET 应用部署在 App Service 上,为什么内存几乎不可能跑到 100%,以及它背后的运行机制、平台限制和真正的排查思路。
先说个结论,这个“内存无法占用100%”的现象,绝大多数情况下不是 bug,而是 App Service 这个平台和 .NET 运行时共同作用下的一个“结果”。理解清楚这里的底层逻辑,远比去代码里硬找“内存泄漏”重要得多。
1. 关于“内存占用100%”这件事,我们到底在讨论什么
1.1 先说清楚,App Service 里的“内存”是谁的内存
很多人把“内存占用”理解成一个简单的进度条——用得多说明应用活跃,用得少说明应用闲着。但放到 App Service 的语境下,内存指的既包含你应用进程(w3wp.exe 或者你自己的进程)本身,也包含托管堆、原生堆、缓存、线程栈,以及 .NET 运行时内部各种结构占用的空间。
在 App Service 里,你查到的“内存使用”指标,往往是来自两个层面:一个是平台层的监控(比如 Azure 门户里看到的 Memory working set),一个是应用进程内部的统计(比如通过诊断工具看到的管理堆大小)。这两个数据之间有差异,因为工作集还包括了更多的内容,比如加载的 DLL、JIT 后的代码、堆里的所有代际对象。
但为什么“跑不满”?这才是问题核心。它牵扯到三个关键因素:应用池回收机制、GC 堆的物理上限、以及平台沙箱对资源可见性的限制。而且我能很负责任地告诉你,大多数情况下,内存跑不满恰恰是“平台在保护你的应用”,而不是“你的应用有问题”。
1.2 一个典型的场景:配置了4GB,但只用了不到300MB
我遇到过最多的提问是这个:“我 App Service 配了 4GB 内存,为什么应用监控面板显示只用了 200MB~300MB?是不是配置没生效?”
碰到这种情况,先别急着加配置。建议你先在 App Service 的“诊断并解决问题”面板里,找到进程快照(Process Snapshot),或者直接用 Kudu 控制台(https://<你的应用名>.scm.azurewebsites.net)打开 PowerShell,查一下当前工作进程的命令行参数。
你大概率会看到一个 -ap 参数,在 .NET Core/.NET 5+ 场景下,甚至会看到环境变量 DOTNET_gcServer 被平台预设。这就是平台层的影响:App Service 会对工作进程做资源限制和配置注入,不只是简单地把进程扔进沙箱里跑。这样做的好处是稳定性,代价就是你没法随心所欲地“压榨”内存。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么 .NET 应用在 App Service 上“跑不满”内存:三大核心原因拆解
2.1 原因一:IIS 的应用程序池回收机制
如果你用的是 .NET Framework 版本的 App Service(Windows 平台),那它背后是经典的 IIS + Application Pool 架构。IIS 的应用程序池默认有 定期回收(Recycling) 机制,默认触发条件是 CPU 达到一定阈值 或 内存达到一定阈值(比如默认是虚拟内存 500MB 或私有内存 1GB 时就回收)。这个阈值是平台默认的,虽然你有机会在 IIS Manager 里看到,但 App Service 的管理配置不一定让你直接改。
更关键的是 闲置超时(Idle Timeout) 设置:如果应用闲置超过 20 分钟(默认值),工作进程会被回收并停止。一旦进程被回收,内存统计会立刻归零。你看到的内存在 300MB 左右波动,很可能就是因为进程在运行一段时间后,达到了某个内存阈值被回收,或者因为闲置被回收,然后重新启动,内存重新累积。
而且在 App Service 里,由于是多租户共享宿主机的架构,IIS 应用池中的 “最大工作进程数” 被设置为 1,所以你没有第二份进程可以分流。你看到的内存曲线“爬不起来”,不是它吃不下,而是它压根就没被允许“吃很久”——到了一定水位,平台就主动让它倒掉了。
注意:这里说的“回收”不等于“崩溃”,而是工作进程结束,然后一个新的工作进程被拉起,应用的静态状态(如内存中的缓存、单例服务等)会丢失一次。
我自己在给客户排查时,最喜欢用的办法是:打开 P
