2014-09-24 8 views
0

많은 응용 프로그램을 실행하는 데 사용하는 Windows Server 2012를 실행하는 컴퓨터가 있습니다. 대부분은 병렬로 많은 비동기 웹 요청을 처리하고 있습니다 (.NET 4.5의 HttpClient 사용).내 서버의 모든 포트가 모두 사용되었습니다. 무엇을 잘못 했습니까?

NETSTAT를 검사하면 거의 모든 사용 가능한 포트 (사용 가능한 포트가 66,536 개임)가 사용되고 있음을 알 수 있습니다. 기본 NETSTAT 호출에서 파이프 된 출력은 64,583 회선이있는 4MB 텍스트 파일입니다. 이것들의 대부분은 TIME_WAIT에 있으며, 롯트는 특정 프로세스에 속하지 않지만 "시스템 프로세스"로 분류됩니다.

TIME_WAIT이 반드시 나쁜 것은 아니며 제 응용 프로그램이 사용 가능한 포트가 없어서 요청을 완료 할 수 없다는 명시 적 예외가 발생하지 않는 것으로 알고 있습니다. 그러나 이것은 나에 관한 것이고 시간 초과를 일으킬 수 있다고 걱정됩니다.

예상 되나요? 레지스트리의 TcpTimedWaitDelay 값을 줄여야합니까? 연결은 기본적으로 TIME_WAIT에 4 분 동안 보관됩니다. 또한 내가이 코드를 열어두고 뭔가 잘못하고있는 것일까 요? 가능한 경우 HttpClient 객체를 재사용하고 완료되면 항상 처리합니다. 연결에주의해야합니까? 답변에 ​​닫기 헤더가 있습니까?

EDIT : 요청한대로 코드를 추가하십시오. 다음은 요청을 만드는 함수입니다 (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 

그리고 요청을 한 예. 그렇지 않으면 를 선언하지 않는 한 HTTP 1.1에서

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

이 질문은 C# 프로그래밍 질문입니까, 아니면 일반적인 컴퓨터 네트워킹 질문입니까? – gunr2171

+0

@ gunr2171 .NET의 HttpClient에만 국한되며 C#으로 코딩됩니다. 나는 연결을 닫아야 하는지를 알고 싶습니다. 그렇다면 연결을 닫아야합니다. 이것들은 나의 어플리케이션이 만들고있는 연결들입니다. 나는 그것이 믿는 코딩 문제입니다. – iguanaman

+0

그러면 우리가 볼 수있는 코드를 게시해야합니다! :) – DavidG

답변

0

, 모든 연결은 영구적 인 것으로 간주됩니다.

그래서 연결을 닫지 않으면 서버는 적어도 일정 시간이 초과 될 때까지 새로운 요청을 기다리게됩니다.

해결책은 Connection: close 헤더를 추가하거나 응답을받은 후 명시 적으로 연결을 닫는 것입니다 (Response.Dispose()).