TLDR - http 客户端连接泄漏修复很好,但您的第一个问题是阻塞线程。再加上你刚刚暴露了敏感数据。也总是先从应用程序池回收而不是 iisreset 开始,以避免关闭整个服务器。
如上所述,您通过使用 using 包装 HTTPClient 泄漏了 TCP 连接,但您已经修复了这个问题,因此这不是主要问题,尽管仍然是一个缩放限制项等待下一个命中。
另外,如果您要耗尽所有 TCP 端口,那会更明显地出现异常,而不是挂起。
查看debugdiag analysis,您的问题似乎是同步 SQL 调用阻塞了 40% 的其他线程。
如果您最终让所有工作线程忙于等待其他阻塞线程,则请求将排队产生挂起,直到请求队列已满并导致 503 服务不可用。
The following threads in w3wp.exe__AppXtender Rest Services__PID__12056__Date__03_28_2017__Time_09_58_36AM__83__Manual Dump.dmp are waiting to enter a .NET Lock
( 33 34 35 50 52 53 54 56 57 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 )
50.91% of threads blocked (56 threads)
据报道,他们正在等待的线程是 55,它运行 SqlCommand.ExecuteReader
有一个async version - ExecuteReaderAsync ,您应该更改为(或让该组件的所有者更改)
Thread 55 - System ID 17820
Entry point clr!Thread::intermediateThreadProc
Create time 3/28/2017 9:51:46 AM
Time spent in user mode 0 Days 00:00:00.421
Time spent in kernel mode 0 Days 00:00:00.187
This thread is waiting on data to be returned from the database server
The current executing command is : SELECT cfgid, cfgvalue FROM ae_cfg WHERE cfgid = 34 and the command timeout is set to 0 seconds.
The connection string for this connection : *** and the connection timeout : 15 seconds.
.NET Call Stack
System_Data_ni!DomainNeutralILStubClass.IL_STUB_PInvoke(SNI_ConnWrapper*, SNI_Packet**, Int32)+84
[[InlinedCallFrame] (.SNIReadSyncOverAsync)] .SNIReadSyncOverAsync(SNI_ConnWrapper*, SNI_Packet**, Int32)
System_Data_ni!SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle, IntPtr ByRef, Int32)+6a
System_Data_ni!System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()+83
System_Data_ni!System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()+7e
System_Data_ni!System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()+65
System_Data_ni!System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte ByRef)+2e
System_Data_ni!System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior, System.Data.SqlClient.SqlCommand, System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.BulkCopySimpleResultSet, System.Data.SqlClient.TdsParserStateObject, Boolean ByRef)+292
System_Data_ni!System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()+5c
System_Data_ni!System.Data.SqlClient.SqlDataReader.get_MetaData()+66
System_Data_ni!System.Data.SqlClient.SqlCommand.FinishExecuteReader(System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.RunBehavior, System.String)+11d
System_Data_ni!System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, Boolean, Int32, System.Threading.Tasks.Task ByRef, Boolean, System.Data.SqlClient.SqlDataReader, Boolean)+ba0
System_Data_ni!System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String, System.Threading.Tasks.TaskCompletionSource`1, Int32, System.Threading.Tasks.Task ByRef, Boolean)+22a
System_Data_ni!System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String)+62
System_Data_ni!System.Data.SqlClient.SqlCommand.ExecuteReader(System.Data.CommandBehavior, System.String)+ca
XtenderSolutions.UtilityLibrary.General.DbCommon.GetStringTypeFromDB(XtenderSolutions.Administration.Database.DbCommonEx)+1aa
XtenderSolutions.UtilityLibrary.General.DbCommon.Open()+11c
XtenderSolutions.CMData.CMConnection.Open()+a7
XtenderSolutions.CMData.CMCfgMgr.Load(XtenderSolutions.CMData.CMConnection, Int16)+55
XtenderSolutions.CMData.CMConnection.InitEAIHooks()+4f
XtenderSolutions.CMData.CMConnection.Init(System.String)+595
XtenderSolutions.CMData.CMConnection..ctor(XtenderSolutions.CMData.CMSession, System.String)+17b
XtenderSolutions.CMData.CMSession.get_Connection()+7e
XtenderSolutions.CMData.CMSession.Login(XtenderSolutions.Configuration.DataSourceConfig, System.String, System.String, System.Security.Principal.WindowsIdentity, System.String, Boolean)+46e
另外,我强烈建议删除您的调试诊断共享或至少删除其中的敏感数据,然后再共享并更改帐户密码。
提示:Basic Auth headers -> base64 -> 明文用户:密码
最后 IISReset:
如果您尚未处于 http.sys 请求队列填满的阶段,您还可以尝试应用程序池回收,它为您提供一个新的 w3wp.exe 工作进程,甚至是池停止/启动,因为您真的没有想要等待当前请求继续挂起。池回收比使整个 IIS 服务器停机的侵入性更小。
但是一旦你在 http.sys 队列中有很多请求,你最终可能需要 iisreset。我总是尽量避免 iisreset 尤其是如果该主机上有其他站点/ vdirs...
您可以监控IIS perf counters并据此做出决定