我们有一个C#Windows服务,它运行一个分为多个任务的进程。大多数任务使用WCF联系Web服务以执行针对数据库的工作。服务的任务在多个线程中运行。
一位客户向我们打开了一个支持案例,称Windows服务偶尔无法响应并需要重新启动。我从Windows服务获得了内存转储。我运行DebugDiag 2.0来分析转储文件。
DebugDiag报告在摘要中有一个有趣的条目:
WindowsService.DMP中的以下线程正在尝试创建HttpWebRequest,但是他们 not 似乎正在等待远程服务器响应(例如,不在线路上#' 39)。这些请求中的一个或多个使用其最大可用连接数的至少一半。
(17 18 27 31 32 33 42)12.07%的线程被阻止(7个线程)
如果许多线程处于此状态,则通常表示限制限制(即“最大连接”设置)已用尽。单击左侧列表中的任何线程,查看它正在等待的WebRequest的限制详细信息。
如有必要,您可以通过修改' maxconnection'来增加可用的连接数。应用程序配置文件中的参数(请参阅
<connectionManagement>
Element),或通过编程方式修改相应的ConnectionLimit属性(请参阅Managing Connections)。
我跳到第17行看到了这个:
第17号线 - 系统ID 4612
入口点mscorwks!Thread :: intermediateThreadProc 创建时间9/10/2015 10:13:14 AM 在用户模式下花费的时间0天00:00:00.000 在内核模式下花费的时间0天00:00:00.000
此线程正在尝试创建HttpWebRequest,但是 not 似乎正在等待远程服务器响应(例如,不是 &#39;在线上&#39;)。这些请求中的一个或多个使用至少一半 其最大可用连接数。
警告,至少有一半的可用连接正在使用
HttpRequest URI:
http://WebServer/MyWebSite/SubDir/MyService.svc
ServicePoint - ConnectionLimit:48 CurrentConnections:44HttpWebRequest对象是一个环回地址,但连接限制仍然适用于此webrequest对象,因为 定义连接限制(通过autoconfig设置为true in processModel部分或通过在里面添加*条目 connectionManagement部分
.NET调用堆栈如下:
Function
[[HelperMethodFrame_1OBJ] (System.Threading.WaitHandle.WaitOneNative)] System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)
mscorlib_ni!System.Threading.WaitHandle.WaitOne(Int64, Boolean)+2f
mscorlib_ni!System.Threading.WaitHandle.WaitOne(Int32, Boolean)+25
System_ni!System.Net.LazyAsyncResult.WaitForCompletion(Boolean)+d3
System_ni!System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest)+2b7
System_ni!System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)+7c
System_ni!System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)+f9
System_ni!System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)+1d3
System_ni!System.Net.HttpWebRequest.GetRequestStream()+e
System_ServiceModel_ni!System.ServiceModel.Channels.HttpOutput+WebRequestHttpOutput.GetOutputStream()+45
System_ServiceModel_ni!System.ServiceModel.Channels.HttpOutput.Send(System.TimeSpan)+f6
System_ServiceModel_ni!System.ServiceModel.Channels.HttpChannelFactory+HttpRequestChannel+HttpChannelRequest.SendRequest(System.ServiceModel.Channels.Message, System.TimeSpan)+121
System_ServiceModel_ni!System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message, System.TimeSpan)+cb
System_ServiceModel_ni!System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message, System.TimeSpan)+17
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannel.Call(System.String, Boolean, System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[], System.TimeSpan)+1a2
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannel.Call(System.String, Boolean, System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[])+33
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage, System.ServiceModel.Dispatcher.ProxyOperationRuntime)+43
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)+65
mscorlib_ni!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)+bd
[[TPMethodFrame] (IMyWebService.GetDataSet)]
IMyWebService.GetDataSet(System.Guid, System.String, System.Data.DataSet)
<service code snipped>
mscorlib_ni!System.Threading.ThreadHelper.ThreadStart_Context(System.Object)+66
mscorlib_ni!System.Threading.ExecutionContext.runTryCode(System.Object)+51
[[HelperMethodFrame_PROTECTOBJ] (System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup)]
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+67
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+45
mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+44
[[GCFrame]]
我看到它提出的建议并开始研究它们。我的问题是:
为什么DebugDiag说线程不似乎在等待服务器响应?
查看.NET Reference Source,请求似乎已成功提交,服务似乎正在等待回复。
更新
打破正常通话,我确实看到一个调用堆栈在Ws2_2等待Puneet Gupta建议如下:
ntdll.dll!_NtWaitForSingleObject@12()
mswsock.dll!_SockWaitForSingleObject@16()
mswsock.dll!_WSPRecv@36()
***ws2_32.dll!_recv@16()***
System.ni.dll!6c084a13()
[Managed to Native Transition]
System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode)
System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags)
System.dll!System.Net.Sockets.NetworkStream.Read(byte[] buffer, int offset, int size)
System.dll!System.Net.PooledStream.Read(byte[] buffer, int offset, int size)
System.dll!System.Net.Connection.SyncRead(System.Net.HttpWebRequest request, bool userRetrievedStream, bool probeRead)
System.dll!System.Net.ConnectStream.ProcessWriteCallDone(System.Net.ConnectionReturnResult returnResult)
System.dll!System.Net.HttpWebRequest.WriteCallDone(System.Net.ConnectStream stream, System.Net.ConnectionReturnResult returnResult)
System.dll!System.Net.ConnectStream.CallDone(System.Net.ConnectionReturnResult returnResult)
System.dll!System.Net.ConnectStream.ResubmitWrite(System.Net.ConnectStream oldStream, bool suppressWrite)
System.dll!System.Net.HttpWebRequest.EndWriteHeaders_Part2()
System.dll!System.Net.HttpWebRequest.EndWriteHeaders(bool async)
System.dll!System.Net.HttpWebRequest.WriteHeadersCallback(System.Net.WebExceptionStatus errorStatus, System.Net.ConnectStream stream, bool async)
System.dll!System.Net.ConnectStream.WriteHeaders(bool async)
System.dll!System.Net.HttpWebRequest.EndSubmitRequest()
System.dll!System.Net.HttpWebRequest.CheckDeferredCallDone(System.Net.ConnectStream stream)
System.dll!System.Net.HttpWebRequest.GetResponse()
System.ServiceModel.dll!System.ServiceModel.Channels.HttpChannelFactory<System.ServiceModel.Channels.IRequestChannel>.HttpRequestChannel.HttpChannelRequest.WaitForReply(System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation)
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message)
mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type)
通常情况下,它会等待来自Windows套接字的响应。在这种情况下,线程可能正在等待连接可用于处理请求 - 如其他DebugDiag消息所示。
答案 0 :(得分:1)
消息说它似乎没有在线路上等待的原因是因为线程上的最后一帧是waithandle.waitone。
对于一个真正在线上等待的线程,我们应该看到ws2_32(在本机堆栈中),它是windows套接字库或托管堆栈中system.net.sockets的一些函数。
你能捕获多个转储吗?如果是,你是否看到一个转储中的线程状态与第二个转储中的状态发生了变化?
答案 1 :(得分:1)
!dso(!DumpStackObjects)是否在当前线程中显示任何连接对象?如果是这样,System.Net.Connection对象中的m_WaitList值是什么,m_CurrentRequest的值是什么? 由于你的callstack没有显示我们正在等待ws2_32(WinSock),这表明HWR仍在等待获得可用连接或套接字。