我们正在处理 .NET 6 中高流量 ASP.NET Core MVC 应用程序中严重的锁争用问题,该应用程序在 IIS Windows Server 中作为进程内托管。
我们正在尝试启用一项功能,对内部服务进行 Http 调用,当我们启用该功能时,我们会发现锁争用增加(来自 dotnet-counters)、CPU 峰值(从 20% 到 100%)、峰值RAM(从 4GB 到 12GB)、线程池中线程数量的增加(从 ~60 到 ~310),显然应用程序很难满足传入的请求。 该问题仅出现在生产环境中,不幸的是我们无法在任何其他环境(本地、UAT、暂存)中重现该问题。
我们进行了无数的转储和跟踪来分析和识别问题,但是所有这些都指向一般的“锁争用增加”问题,并且热路径始终是此堆栈跟踪:
ntdll.dll!NtRemoveIoCompletion()
KERNELBASE.dll!GetQueuedCompletionStatus()
System.Private.CoreLib.dll!00007ff803838421()
[Managed to Native Transition]
System.Private.CoreLib.dll!System.Threading.LowLevelLifoSemaphore.WaitForSignal(int timeoutMs = 0x00004e20)
System.Private.CoreLib.dll!System.Threading.LowLevelLifoSemaphore.Wait(int timeoutMs, bool spinWait)
System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
System.Private.CoreLib.dll!System.Threading.Thread.StartCallback()
[Native to Managed Transition]
kernel32.dll!BaseThreadInitThunk()
ntdll.dll!RtlUserThreadStart()
实际上,我们看到前后转储中的线程数量大幅增加,所有线程都指向等待 GetQueuedCompletionStatus() 方法的 IOCP 线程。
不幸的是,我们无法识别产生 IOCP 线程的工作线程,并且我们不知道有任何方法将 IOCP 线程关联到 IOCP 端口和相关工作线程。
我们正在盲目地尝试进行与异步实现相关的更改,但仍然没有成功。
我们还尝试了所有 HttpClient 模式,只是为了确保我们没有遗漏一些明显的东西: 静态 HttpClient 寿命长 使用 IHttpClientFactory 的短暂命名 HttpClient 实例 长期存在的 HttpClient 实例的自定义池
我们已将最小工作线程和 iocp 线程设置为 200,然后从默认值设置为 300,但仍然没有运气或应用程序的行为发生任何变化。
运行syncblk不会显示任何内容(未检测到同步锁),也不会显示任何其他从转储或跟踪中识别锁/争用的常见方法。
我真的很感激任何对此的反馈,因为我们已经在墙上撞了一个多月了,谢谢! :)
这个问题有运气吗?遇到同样的问题,我猜测它与此ASP.Net Core Thread Starvation in high load
有关尚未尝试链接上的解决方案。