我有一台运行Windows Server 2012的计算机,用于运行我的许多应用程序。他们中的大多数都是并行处理许多异步Web请求(使用.NET 4.5中的HttpClient)。
当我检查NETSTAT时,我看到几乎所有可用的端口(假设66,536是最大值)端口正在使用中。基本NETSTAT调用的管道输出是一个4mb文本文件,有64,583行。其中大部分都在TIME_WAIT中,批次不属于任何特定流程,但标记为"系统流程"。
我理解TIME_WAIT不一定是坏事,我的应用程序似乎没有明确地抛出异常,说明由于没有可用端口而无法完成请求。然而,这令我担忧,我担心它可能会导致超时。
这是预期的吗?我应该减少注册表中的TcpTimedWaitDelay值吗?我认为默认情况下连接在TIME_WAIT中保持4分钟。还有可能我在我的代码中做了一些错误的事情,让连接保持开放状态吗?我尽可能重用HttpClient对象,并在完成后始终处理它。我应该注意连接:在回复中关闭标题吗?
编辑:根据要求添加代码。这是发出请求的函数(HttpClient的自定义类包装器的一部分);
Public Async Function WebRequestAsync(Url As String, Optional RequestMethod As RequestMethod = RequestMethod.GET, Optional Content As Object = Nothing, _
Optional ContentType As ContentType = ContentType.Default, Optional Accept As String = DefaultAcceptString, _
Optional AdditionalHeaders As NameValueCollection = Nothing, Optional Referer As String = Nothing, _
Optional NoCache As Boolean = False, Optional CustomCookieHandler As Boolean = False, _
Optional Attempts As Integer = 2, Optional CanBeCancelled As Boolean = True) _
As Tasks.Task(Of HttpResponseMessage)
If Attempts < 1 Then Attempts = 1
Dim Method As HttpMethod = Nothing
Select Case RequestMethod
Case Variables.RequestMethod.DELETE : Method = HttpMethod.Delete
Case Variables.RequestMethod.GET : Method = HttpMethod.Get
Case Variables.RequestMethod.OPTIONS : Method = HttpMethod.Options
Case Variables.RequestMethod.POST : Method = HttpMethod.Post
Case Variables.RequestMethod.PUT : Method = HttpMethod.Put
End Select
'prepare message
Dim Message As New HttpRequestMessage(Method, Url)
Message.Headers.ExpectContinue = False
Message.Headers.TryAddWithoutValidation("Accept", Accept)
If Referer IsNot Nothing Then Message.Headers.Add("Referer", Referer)
If NoCache Then
Message.Headers.Add("Pragma", "no-cache")
Message.Headers.Add("Cache-Control", "no-cache")
End If
If AdditionalHeaders IsNot Nothing Then
For Each Key In AdditionalHeaders.AllKeys
Message.Headers.TryAddWithoutValidation(Key, AdditionalHeaders(Key))
Next
End If
'set content
If Content IsNot Nothing Then
Dim ContentTypeString As String = GetEnumDescription(ContentType)
Dim ContentBytes As Byte() = Nothing
If TypeOf Content Is String Then
ContentBytes = Encoding.UTF8.GetBytes(CType(Content, String))
ElseIf TypeOf Content Is Byte() Then
ContentBytes = CType(Content, Byte())
ElseIf TypeOf Content Is MultiPartPostData Then
Dim MultiPartPostData As MultiPartPostData = CType(Content, MultiPartPostData)
ContentBytes = MultiPartPostData.Bytes
ContentTypeString += "; boundary=" & MultiPartPostData.Boundary
End If
Dim ByteArrayContent As New ByteArrayContent(ContentBytes)
ByteArrayContent.Headers.Add("Content-Type", ContentTypeString)
Message.Content = ByteArrayContent
End If
'get response
Output(RequestMethod.ToString & " " & Url, OutputType.Debug)
'Set cancellation token
Dim CToken As New CancellationToken
If CancellationToken IsNot Nothing AndAlso CancellationToken.HasValue AndAlso CanBeCancelled Then CToken = CancellationToken.Value
Dim Response As HttpResponseMessage = Nothing
For Attempt = 1 To Attempts
Try
Response = Await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead, CToken).ConfigureAwait(False)
Catch ex As Tasks.TaskCanceledException
If DebugMode Then Output(Method.ToString & " " & Url & " Timed out", OutputType.Error)
Catch ex As HttpRequestException
If ex.InnerException IsNot Nothing Then
If DebugMode Then Output(Method.ToString & " " & Url & " " & ex.InnerException.Message, OutputType.Error)
If ex.InnerException.Message = "Timed out" Then Continue For
Else
If DebugMode Then Output(Method.ToString & " " & Url & " " & ex.Message, OutputType.Error)
End If
Catch ex As Exception
If DebugMode Then Output(Method.ToString & " " & Url & " " & ex.Message, OutputType.Error)
End Try
Exit For
Next
If Response IsNot Nothing Then
Output(Method.ToString & " " & Url & " " & Response.StatusCode & " " & Response.StatusCode.ToString, OutputType.Debug)
If CustomCookieHandler AndAlso Cookies IsNot Nothing Then
Dim Values As IEnumerable(Of String) = Nothing
If Response.Headers.TryGetValues("Set-Cookie", Values) Then ManuallyExtractCookies(Values, New Uri(Url).GetLeftPart(UriPartial.Authority))
End If
End If
Return Response
End Function
提出请求的一个例子;
Using HttpClient As New HttpClientWrapper(User, Task)
Dim Response As String = Await HttpClient.WebRequestStringAsync("http://www.google.com")
If Response Is Nothing Then Return Nothing
End Using
答案 0 :(得分:0)
在HTTP 1.1中,除非声明,否则所有连接都被视为持久连接 否则。
因此,如果您不关闭连接,服务器将继续等待新请求(至少在某个超时之前)。
解决方案是在收到响应后添加Connection: close
标头或明确关闭连接:Response.Dispose()
。