2017-11-16 10 views
0

다음 문제가 발생했습니다. IIS 서버와 동일한 지역에있는 서버에 500ms마다 요청을 보내는 .Net 모듈에서 작업하고 있습니다. 대부분의 요청 (약 99 %)은 약 1 ~ 3ms가 소요됩니다. 그러나 이러한 요청 중 일부는 시간 초과되었습니다 (저는 WebRequest.Timeout을 150ms로 설정했습니다.)..Net 모듈의 이상한 시간 초과 문제

이 이상한 일이 :

  • 우선 다른 요청이 번개 같은 빠른만큼 이상한 무한 할 수있는 제한 시간을 설정하면 요청을 실행하는 데 약 ~ 180ms 걸릴 것이다 시간 제한
  • 때 WebException을 잡기 때문에 을 150ms로 설정하는 동안 WebRequest.GetResponse()과 예외가 발생하는 순간 사이에 ~ 350ms를 측정합니다.

    ApiResult IApiService.Request(IConnectorRequest request) 
    { 
        long timestamp = 0; 
        DebugStream debug = null; 
    
        try 
        { 
         var dictionary = CollectData(request); 
    
         //TODO:May be include some ServicePoint information. 
         //APIConnectionState=Reused 
    
         // Sending request to the API ////////////////////////////////////////////////////// 
         var http = CreateRequest(); 
    
         Stream stream; 
         using (stream = http.GetRequestStream()) 
         { 
          if (_Log.IsDebug) 
          { 
           stream = debug = new DebugStream(stream, _Encoding); 
          } 
    
          dictionary.WriteForm(stream, _Encoding); 
         } 
    
         if (debug != null) 
         { 
          _Log.Debug("WebRequestApiService.Request({0:N}): {1}", request.Id, debug.Data); 
         } 
    
         // Start request and fix timestamp before execution. 
         timestamp = Stopwatch.GetTimestamp(); 
         var response = http.GetResponse() as HttpWebResponse; 
         // (Stopwatch.GetTimestamp() - timestamp)/TimeSpan.TicksPerMillisecond => ~2ms 
    
         if (response == null) 
         { 
          const string message = "Response is not HttpWebResponse"; 
          _Log.Warning("WebRequestApiService.Request({0:N}): {1}", request.Id, message); 
    
          return ApiResult.Failure(message); 
         } 
         response.GetRequestHeaders(); 
         return new ApiResult() 
         { 
          StatusCode = (int)response.StatusCode, 
          Description = response.StatusDescription, 
          DataDomeStatus = response.GetStatusHeader(), 
          Headers = response.GetHeaders() 
         }; 
        } 
        catch (WebException we) 
        { 
         var errorMessage = string.Empty; 
         var response = we.Response as HttpWebResponse; 
         Exception e; 
    
         if (response != null) 
         { 
          errorMessage = response.GetText(out e); 
    
          if (response.StatusCode == HttpStatusCode.Forbidden) 
          { 
           return new ApiResult() 
           { 
            StatusCode = (int)response.StatusCode, 
            Description = response.StatusDescription, 
            DataDomeStatus = response.GetStatusHeader(), 
            Headers = response.GetHeaders(), 
            Content = errorMessage 
           }; 
          } 
    
          if (errorMessage == null) 
          { 
           _Log.Warning("WebRequestApiService.Request({0}): Problem getting response {1}", request.Id, e); 
          } 
         } 
    
         // (Stopwatch.GetTimestamp() - timestamp)/TimeSpan.TicksPerMillisecond => ~350ms 
         _Log.Warning(
          "WebRequestApiService.Request({0}): Message={1}\nTimeout={2}\nError=\n{3}\n\nRequest=\n{4}\n\nAPI=\n{5}\n", 
          request.Id, 
          errorMessage, 
          (Stopwatch.GetTimestamp() - timestamp)/TimeSpan.TicksPerMillisecond, 
          we, 
          request.Dump(), 
          debug != null ? debug.Data : "NULL" 
         ); 
    
         return ApiResult.Failure(errorMessage); 
        } 
        catch (Exception e) 
        { 
         _Log.Warning(
          "WebRequestApiService.Request({0}): Timeout={1}\nError=\n{2}\n\nRequest=\n{3}\n\nAPI=\n{4}\n", 
          request.Id, 
          (Stopwatch.GetTimestamp() - timestamp)/TimeSpan.TicksPerMillisecond, 
          e, 
          request.Dump(), 
          debug != null ? debug.Data : "NULL" 
         ); 
    
         return ApiResult.Failure(e.Message); 
        } 
    } 
    

    을 그리고 이것은 사용되는 방법입니다 : 레거시 코드의 성능이 차이가 정말 우리에게 문제가하고

이 일어나고 왜 이해가 안 돼요을 내가 일하고 있어요된다 우리의 HttpWebRequest를 만들 수 있습니다 :

private HttpWebRequest CreateRequest() 
{ 
    var http = WebRequest.Create(_uri) as HttpWebRequest; 

    if (http == null) 
    { 
     throw new NotImplementedException(); 
    } 

    // Disable proxy (if node proxy configuration in config file). Otherwise the first 
    // request will be slowed down due the proxy auto-detection. 
    if (_noProxy) 
    { 
     http.Proxy = null; 
    } 

    // Configure timeout. 150ms in our case 
    http.Timeout = _timeout; 

    // Force connection to be keep-alive. 
    http.KeepAlive = true; 

    // Disable caching. 
    http.CachePolicy = _cachePolicy; 

    // Basic request fields 
    http.Method = "POST"; 
    http.ContentType = "application/x-www-form-urlencoded"; 
    http.UserAgent = null; 

    // If auto redirect is allowed, then we can't catch redirect response from API server. 
    http.AllowAutoRedirect = false; 

    return http; 
} 

사람이 WebRequest 클래스의 동작을 알고는 무거운 약간의 성능 저하가 왜 내가 경험하고로합니까? 타임 아웃을 150ms로 설정하면 예외가 350ms에 잡히게되는 이유는 무엇입니까? (이는 성능이 심각한 문제입니다).

는 정말 내가이 세계에 새로 온 사람하고 있기 때문에 고객이 제약

요청 더 C#에서 경험과 닷넷 사람에서 도움이 같은 사전에 감사합니다 것

답변

0

문제는 가능성이 DNS이다 쿼리 관련. documentationTimeout에 대한 상태 :

도메인 이름 시스템 (DNS) 쿼리 또는 시간을 반환 15 초까지 걸릴 수 있습니다. 요청에 해상도가 필요한 호스트 이름이 포함되어 있고 Timeout을 15 초 미만의 값으로 설정하면 요청시 시간 초과를 나타내는 WebException이 throw되기 전에 이 15 초 이상 걸릴 수 있습니다.

+0

DNS 조회와 관련이 없다고 생각합니다. 내 .Net 응용 프로그램에서 DNS 조회에 대한 트래픽을 스니핑하여 아이디어를 확인하려고 시도했습니다. 결과는 10 분 및 1000 회의 요청에 대해 4 회의 DNS 조회 만 수행되었으며 50 회의 시간 초과가 발생했습니다. 또한 시간 초과 날짜와 DNS 조회 날짜가 일치하지 않습니다. –