2017-11-24 3 views
1

정적 HttpClient와 솔루션을 사용하는 몇 가지 기사와 함정을 읽었습니다. 기사 중 하나는 - http://byterot.blogspot.ca/2016/07/singleton-httpclient-dns.htmlHttpClient - DNS 변경 사항이 적용되지 않습니다.

솔루션을 구현했으며 실제로 제안 된 내용이 실제로 작동하는지 테스트하려고합니다. 내가 피들러의 트래픽을 볼 때

 Task.Run(async() => 
     { 
      using (var httpClient = new HttpClient(new ApiHandler())) 
      { 
       var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers"); 
       var result = await httpResponse.Content.ReadAsStringAsync(); 
       Console.WriteLine(result); 
      } 
     }).ContinueWith(async task => 
     { 
      await Task.Delay(5000); 
      using (var httpClient = new HttpClient(new ApiHandler())) 
      { 
       var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers"); 
       var result = await httpResponse.Content.ReadAsStringAsync(); 
       Console.WriteLine(result); 
      } 
     }).ContinueWith(async task => 
     { 
      await Task.Delay(10000); 
      using (var httpClient = new HttpClient(new ApiHandler())) 
      { 
       var httpResponse = await httpClient.GetAsync("https://test.com/api/Tiers"); 
       var result = await httpResponse.Content.ReadAsStringAsync(); 
       Console.WriteLine(result); 
      } 
     }); 

: 예상대로

enter image description here

동작이

다음

우리가 피하려고하는 코드입니다. 각각의 생성 및 처리는 요청 및 응답이 완료 될 때 연결이 설정되도록합니다.

: 이전 이미지 그러나 그것은 다음과 같이 보이는

private static readonly HttpClient HttpClient = new HttpClient(new ApiHandler()); 
    static void Main() 
    { 
     ServicePointManager 
      .FindServicePoint(new Uri("https://test.com")) 
      .ConnectionLeaseTimeout = 1000; // 1 second 
     ServicePointManager.DnsRefreshTimeout = 1000; // 1 second 

     Task.Run(async() => 
     { 
      var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers"); 
      var result = await httpResponse.Content.ReadAsStringAsync(); 
      Console.WriteLine(result); 
     }).ContinueWith(async task => 
     { 
      await Task.Delay(5000); // delay 5 seconds 
      var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers"); 
      var result = await httpResponse.Content.ReadAsStringAsync(); 
      Console.WriteLine(result); 
     }).ContinueWith(async task => 
     { 
      await Task.Delay(10000); // delay 10 seconds 
      var httpResponse = await HttpClient.GetAsync("https://test.com/api/Tiers"); 
      var result = await httpResponse.Content.ReadAsStringAsync(); 
      Console.WriteLine(result); 
     }); 

     Console.ReadKey(); 
    } 

내가 같은 동작을 기대 :

HttpClient를를 사용하기에 적합한 제안 된 방법은 정적 할이다 enter image description here

그리고 내가 HttpClient.DefaultRequestHeaders.ConnectionClose = true;을 추가하면 원하는 결과를 얻을 수 있습니다. 그러나 이것이 우리가 피하고 싶은 것입니다 - 각 요청 응답이 연결을 만들 때입니다.

피들러가 원하는 결과가 맞습니까? 또는 ConnectionLeaseTimeout 및/또는 DnsRefreshTimeout을 설정하여 무언가를 놓치고 있습니까? 이 동작을 테스트하고 ServicePointManager에 해당 속성을 설정하면 HttpClient의 정적 인스턴스로 DNS 알려진 문제가 해결됩니다.

답변

3

Fiddler는 자신을 프록시로 등록합니다. 기본적으로는 127.0.0.1에서 수신 대기 포트 8888 그래서 당신이해야 할 당신의 사건에 대한 정확한 서비스 지점 개체를 얻을 :

ServicePointManager.FindServicePoint(
    new Uri("https://test.com"), 
    new WebProxy(new Uri("http://127.0.0.1:8888"))) 
.ConnectionLeaseTimeout = 1000; // 1 second 

이제 올바른 결과를 볼 수 있습니다. 예상대로 정확하지는 않습니다. 첫 번째 요청은 새 연결을 엽니 다. 두 번째 요청은 이 아니며은 5 초가 지난 후에도 새 연결을 엽니 다. 대신 요청시 Connection: close 헤더를 설정하여 연결을 닫아야 함을 나타냅니다. 그런 다음 다음 요청 (세 번째)이 마침내 새 연결을 시작합니다. 이것은 내가 ConnectionLeaseTimeout에 대해 말할 수있는 한 예상되는 행동입니다.

+0

놀라워요! 고맙습니다!! –

관련 문제