환경 : Windows Server 2012 R2 64 비트. C# .NET Framework 버전 4.5.1.여러 스레드 사이에서 단일 HttpClient를 다시 사용할 때 소켓 부족 - TIMED_WAIT 연결의 1000 초 남음
내가하여 SharePoint 2013 사이트에서 파일들을 다운로드하는이 프로그램을 사용하는 것을 시도하고있다 : https://github.com/nddipiazza/Sharepoint-Exporter
이 프로젝트에서 파일을 다운로드 요청을 끌어 [FileDownloader.cs] [1] 파일이 BlockingCollection에 저장하고 파일에 다운로드합니다. 나는이 프로그램을 실행할 때
내가 꽤 빨리 소켓 오류 때리게 : 나는 너무 열심히이 코드를 타격하고 같은
System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted 10.5.50.2:443
at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at SpPrefetchIndexBuilder.FileDownloader.attemptToDownload(FileToDownload toDownload, Int32 numRetry)
---> (Inner Exception #0) System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted 10.5.50.2:443
at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace ---<---
를 기본적으로 같다 :
public void AttemptToDownload(FileToDownload toDownload, int numRetry)
{
try
{
var responseResult = client.GetAsync(SpPrefetchIndexBuilder.topParentSite + toDownload.serverRelativeUrl);
if (responseResult.Result != null && responseResult.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
using (var memStream = responseResult.Result.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
{
using (var fileStream = File.Create(toDownload.saveToPath))
{
memStream.CopyTo(fileStream);
}
}
Console.WriteLine("Thread {0} - Successfully downloaded {1} to {2}", Thread.CurrentThread.ManagedThreadId, toDownload.serverRelativeUrl, toDownload.saveToPath);
}
else
{
Console.WriteLine("Got non-OK status {0} when trying to download url {1}", responseResult.Result.StatusCode, SpPrefetchIndexBuilder.topParentSite + toDownload.serverRelativeUrl);
}
}
catch (Exception e)
{
if (numRetry >= NUM_RETRIES)
{
Console.WriteLine("Gave up trying to download url {0} to file {1} after {2} retries due to error: {3}", SpPrefetchIndexBuilder.topParentSite + toDownload.serverRelativeUrl, toDownload.saveToPath, NUM_RETRIES, e);
}
else
{
AttemptToDownload(toDownload, numRetry + 1);
}
}
}
뭔가 잘못 거기 방법으로 I HttpClient를 사용하고 있습니까? 모든 포럼을 읽었으며 정적 참조를 다시 사용하라고 말하고 있습니다. 모든 스레드는 동일한 정적 HttpClient 참조를 공유합니다.
여기는 다운로드가 몇 분 동안 실행 된 때의 netstat -a -o -n
입니다. TIMED_WAIT이 (가) 많이 있습니다. https://pastebin.com/GTYmqwue이 테스트에서는 포트 80에서 SharePoint를 사용하고있었습니다. 왜 그런가요?
몇 분 후에 다시 실행하면 TIMED_WAIT의 수가 수백 개 증가합니다. 어떤 종류의 누수가 있어야 하나?
HttpClient가 1000 개의 TIMED_WAIT 연결을 그대로 두는 이유는 무엇입니까? 어떻게 닫을 수 있습니까?
ServiePointManager.DefaultConnectionLimit = numThreads
으로 설정하려고했으나 여전히 연결 수가 1000 개가됩니다.
어떤 운영 체제입니까? –
중복 된 것으로 보입니다. - https://stackoverflow.com/questions/2960056/trying-to-run-multiple-http-requests-in-parallel-but-being-limited-by-windows –
단일 HttpClient에는 한 번에 처리 할 수있는 많은 동시 요청 만 있습니다. 루프에서 비동기를 사용하는 경우 1000s의 요청을 쉽게 시작하는 것이 어렵지 않습니다. –