我们最近一直在生产服务器上遇到一组定期发生的CPU高峰,特别是星期二晚上(有时是星期一晚上),间隔15-20分钟(有时更少),到目前为止,我们已经缩小了范围直到w3wp.exe(ASP.NET)进程,但仍无法确定出现峰值的确切原因。
我们已经尝试了一些在线监视工具,但是并没有带来任何可喜的结果。
我发现最接近的结果是使用WinDbg,并在CPU出现峰值时查看进程转储。
运行“!syncblk”命令以确定哪些线程具有锁时,我收到以下结果,该结果不包含线程ID供我进一步研究
!syncblk Index SyncBlock MonitorHeld Recursion Owning Thread
Info SyncBlock Owner 163 00000000119712e8 410 0
0000000000000000 none 00000004bff6b488
System.Threading.TimerQueue
我还尝试分析一些运行时间更长的线程,并且我看到的唯一共同点是堆栈跟踪中的以下内容。
000000002863ba28 000000007712c2ea [GCFrame: 000000002863ba28]
000000002863baf8 000000007712c2ea [HelperMethodFrame_1OBJ: 000000002863baf8] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
000000002863bc10 000007fe9cdfaadd System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\System\Threading\ManualResetEventSlim.cs @ 670]
000000002863bcd0 000007fe9cdf9ceb System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\System\Threading\Tasks\Task.cs @ 3356]
000000002863bd60 000007fe9cdf946a System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\System\Threading\Tasks\Task.cs @ 3295]
000000002863be60 000007fe9cdf91d5 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) [f:\dd\ndp\clr\src\BCL\System\Runtime\CompilerServices\TaskAwaiter.cs @ 167]
000000002863be90 000007fe9cd776f1 System.Runtime.CompilerServices.TaskAwaiter`1[[Microsoft.AspNet.Identity.Owin.SignInStatus, Microsoft.AspNet.Identity.Owin]].GetResult() [f:\dd\ndp\clr\src\BCL\System\Runtime\CompilerServices\TaskAwaiter.cs @ 373]
000000002863bec0 000007fe9cd774ab Microsoft.AspNet.Identity.AsyncHelper.RunSync[[Microsoft.AspNet.Identity.Owin.SignInStatus, Microsoft.AspNet.Identity.Owin]](System.Func`1>)
当试图验证用户身份时,AspNet.Identity类似乎存在某种锁定问题。这特别发生在ASP.NET Web API中“ AuthorizeAttribute”类的实现中,在该实现中,我们使用OWIN来验证用户身份。
此外,我们似乎被锁定的其他一些线程从WinDbg获得以下输出,但我不确定是否相关。
00000000048ddc28 000000007712c2ea [GCFrame: 00000000048ddc28]
00000000048dde20 000000007712c2ea [GCFrame: 00000000048dde20]
00000000048dde58 000000007712c2ea [HelperMethodFrame: 00000000048dde58] System.Threading.Monitor.Enter(System.Object)
00000000048ddf50 000007fe9c6403d5 System.Threading.TimerQueueTimer.Fire() [f:\dd\ndp\clr\src\BCL\System\Threading\Timer.cs @ 658]
00000000048ddfc0 000007fe9a98ccf3 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() [f:\dd\ndp\clr\src\BCL\System\Threading\ThreadPool.cs @ 1260]
00000000048de010 000007fe9a98b143 System.Threading.ThreadPoolWorkQueue.Dispatch() [f:\dd\ndp\clr\src\BCL\System\Threading\ThreadPool.cs @ 830]
00000000048de578 000007fef8e1afb3 [DebuggerU2MCatchHandlerFrame: 00000000048de578]
00000000048de708 000007fef8e1afb3 [ContextTransitionFrame: 00000000048de708]
00000000048de928 000007fef8e1afb3 [DebuggerU2MCatchHandlerFrame: 00000000048de928]
对此绝对有帮助。
更新... 经过更多调查后,我似乎发现了两种不同的模式:
首先-我们有一些长时间运行的线程似乎正在等待返回不成功的API响应(很可能是通过取消令牌)
第二个-当查看阻塞其他线程的线程时,我看到的一个共同主题是它正在等待计时器以使MemoryCache对象中的项目过期。
我不确定我所查看的内容是否有助于确定原因。