Azure Functions Kudu w3wp.exe抛出OutOfMemoryException求助排查
问题概述
使用P3V3定价层专用App Service计划,部署9个Azure Functions+2个Web应用,采用手动单实例配置。内存监控显示:实际业务函数仅占用500MB内存,但Kudu(SCM站点)内存频繁飙升至12GB,w3wp.exe[SCM]进程反复抛出OutOfMemoryException;其中一个已标记待移除、未被调用的函数,其Kudu内存偶尔也会涨到10GB。
函数配置详情:
- 8个函数:运行时
dotnet,目标框架net3.1,Functions版本v3 - 1个函数:运行时
dotnet-isolated,目标框架net7.0,Functions版本v4
翻译后的Kudu事件日志报错信息
ASP.NET 4.0.30319.0 | 事件ID:1325 | 时间:2024-09-09 16:23:26
发生未处理异常,进程已终止。
应用ID: /LM/W3SVC/695954313/ROOT
进程ID: 568
异常类型:System.OutOfMemoryException
调用栈:at System.Text.StringBuilder.ToString() at System.Diagnostics.AsyncStreamReader.ReadBuffer(IAsyncResult ar) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.IO.Stream.ReadWriteTask.System.Threading.Tasks.ITaskCompletionAction.Invoke(Task completingTask) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.Finish(Boolean bUserDelegateExecuted) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot) at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) at System.Threading.ThreadPoolWorkQueue.Dispatch()
.NET Runtime | 事件ID:1026 | 时间:2024-09-09 16:23:26
应用: w3wp.exe
框架版本: v4.0.30319
描述: 进程因未处理异常而终止。
异常类型:System.OutOfMemoryException
调用栈:at System.Text.StringBuilder.ToString() at System.Diagnostics.AsyncStreamReader.ReadBuffer(System.IAsyncResult) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.IO.Stream+ReadWriteTask.System.Threading.Tasks.ITaskCompletionAction.Invoke(System.Threading.Tasks.Task) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.Finish(Boolean) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.ExecuteEntry(Boolean) at System.Threading.ThreadPoolWorkQueue.Dispatch()
ASP.NET 4.0.30319.0 | 事件ID:1325 | 时间:2024-09-09 17:14:02
发生未处理异常,进程已终止。
应用ID: /LM/W3SVC/695954313/ROOT
进程ID: 12464
异常类型:System.OutOfMemoryException
调用栈:at System.Text.StringBuilder.set_Length(Int32 value) at System.Diagnostics.AsyncStreamReader.ReadBuffer(IAsyncResult ar) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.IO.Stream.ReadWriteTask.System.Threading.Tasks.ITaskCompletionAction.Invoke(Task completingTask) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.Finish(Boolean bUserDelegateExecuted) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot) at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) at System.Threading.ThreadPoolWorkQueue.Dispatch()
.NET Runtime | 事件ID:1026 | 时间:2024-09-05 16:33:59
应用: w3wp.exe
框架版本: v4.0.30319
描述: 进程因未处理异常而终止。
异常类型:System.OutOfMemoryException
调用栈:at System.Text.StringBuilder.set_Length(Int32) at System.Diagnostics.AsyncStreamReader.ReadBuffer(System.IAsyncResult) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.IO.Stream+ReadWriteTask.System.Threading.Tasks.ITaskCompletionAction.Invoke(System.Threading.Tasks.Task) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.Finish(Boolean) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.ExecuteEntry(Boolean) at System.Threading.ThreadPoolWorkQueue.Dispatch()
ASP.NET 4.0.30319.0 | 事件ID:1325 | 时间:2024-09-05 16:58:43
发生未处理异常,进程已终止。
原因分析
从报错栈可以明确,内存溢出发生在SCM站点的流读取逻辑中——AsyncStreamReader.ReadBuffer方法在操作StringBuilder时耗尽内存。结合场景,触发点可能包括:
- 待移除的未调用函数存在残留的日志生成、文件监听逻辑,SCM站点扫描该函数资源时触发内存泄漏;
- .NET 3.1(已停止支持)与Functions v3的组合,和SCM站点旧版本工具链存在兼容性问题,导致内存管理失效;
- 单个实例承载11个应用(9个函数+2个Web),SCM站点同时处理多个应用的日志同步、文件扫描操作,内存负载叠加后耗尽;
- SCM站点默认无内存限制,一旦出现流读取未截断的情况,会持续占用内存直到溢出。
解决步骤
1. 优先移除未使用的函数
立即删除那个未被调用的待移除函数,观察Kudu内存是否恢复正常——这是最快速的排查手段,排除该函数的异常影响。
2. 拆分App Service计划负载
将部分函数或Web应用迁移到独立的App Service计划,减少单个实例的应用数量,避免SCM站点因同时处理多个应用的操作而内存过载。
3. 升级.NET 3.1函数到高版本
.NET 3.1已停止官方支持,将8个.net3.1的Functions v3应用升级到.NET 6/7,并切换到Functions v4(非隔离或隔离模式),修复旧版本与SCM站点的兼容性问题,同时获得安全更新。
4. 配置SCM站点内存限制
在App Service的应用设置中添加WEBSITE_SCM_MAX_MEMORY_LIMIT_MB参数,设置合理阈值(如4096MB),当SCM进程内存超过阈值时自动重启,避免占用过多实例内存。
5. 优化SCM站点日志配置
关闭不必要的实时日志监控、日志自动同步功能,减少SCM站点的IO操作和内存占用。
6. 切换到自动缩放模式
关闭手动单实例配置,开启基于内存阈值的自动缩放策略,当实例内存占用过高时自动新增实例分摊负载。
7. 临时缓解方案
如果内存溢出紧急,可通过Kudu站点的Process Explorer手动终止w3wp.exe[SCM]进程,或重启整个App Service实例临时恢复服务。
内容的提问来源于stack exchange,提问作者JavaDeveloper

