2017-09-09 22 views
0

저는 OWIN을 사용하는 콘솔 응용 프로그램에서 작은 웹 응용 프로그램을 자체 호스팅합니다.Owin의 최대 동시 요청 수

ApiController에 도달하면 등록 된 하나의 미들웨어있다 전에 : 관심의 메인 라인 인 즉 여기 Next.Invoke는, 기본적으로 비동기 적으로 다른 API에 HTTP 요청을 전달 컨트롤러 메소드를 호출

public class HealthcheckMiddleware : OwinMiddleware 
{ 
    private readonly string DeepHealthEndpointPath = "/monitoring/deep"; 
    private readonly string ShallowHealthEndpointPath = "/monitoring/shallow"; 

    public HealthcheckMiddleware(OwinMiddleware next) 
     : base(next) 
    { 
    } 

    public async override Task Invoke(IOwinContext context) 
    { 
     try 
     { 
      string requestPath = context.Request.Path.Value.TrimEnd('/'); 
      if (requestPath.Equals(ShallowHealthEndpointPath, StringComparison.InvariantCultureIgnoreCase) 
       || requestPath.Equals(DeepHealthEndpointPath, StringComparison.InvariantCultureIgnoreCase)) 
      { 
       context.Response.StatusCode = (int) HttpStatusCode.OK; 
      } 
      else 
      { 
       await Next.Invoke(context); 
      } 
     } 
     catch (Exception ex) 
     { 
      // This try-catch block is inserted for debugging 
     } 
    } 
} 

가 :

var response = await _httpClient.SendAsync(outgoingRequest); 

그러나,이 같은 API

(필자는 API에 preassure를 넣어 원하는 목적에 그들을 기다리고되지 않음) 10 개 HTTP 요청을 제출하려고하면

경우 InvalidOperationException :

for (int i = 0; i < 10; i++) 
{ 
    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5558/forwarder"); 
    httpRequestMessage.Content = new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, "application/json"); 
    httpClient.SendAsync(httpRequestMessage); 
} 

후 즉시 나중에 10 이상을 제출 한 후 나는 HealthcheckMiddleware의 catch 블록에서 다음과 같은 예외가이 작업이 제출 된 응답 후 수행 할 수 없습니다.

스택 트레이스 : I에 유래와 구글 모두 검색을 시도했지만, 가치의 아무것도 찾을 수 없습니다

at System.Net.HttpListenerResponse.set_ContentLength64(Int64 value) 
at Microsoft.Owin.Host.HttpListener.RequestProcessing.ResponseHeadersDictionary.Set(String header, String value) 
at Microsoft.Owin.Host.HttpListener.RequestProcessing.HeadersDictionaryBase.Set(String key, String[] value) 
at Microsoft.Owin.Host.HttpListener.RequestProcessing.HeadersDictionaryBase.set_Item(String key, String[] value) 
at Microsoft.Owin.HeaderDictionary.System.Collections.Generic.IDictionary<System.String,System.String[]>.set_Item(String key, String[] value) 
at System.Web.Http.Owin.HttpMessageHandlerAdapter.SetHeadersForEmptyResponse(IDictionary`2 headers) 
at System.Web.Http.Owin.HttpMessageHandlerAdapter.SendResponseMessageAsync(HttpRequestMessage request, HttpResponseMessage response, IOwinResponse owinResponse, CancellationToken cancellationToken) 
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<InvokeCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
at DataRelay.NonGuaranteedDataForwarder.HealthcheckMiddleware.<Invoke>d__3.MoveNext() in C:\_code\DataRelay.NonGuaranteedDataForwarder\HealthcheckMiddleware.cs:line 30 

. 예를 들어 this을 찾았지만 여기서는 개발자가 요청을 제출 한 후에 읽습니다. 요청하지 않습니다.

그냥 경우에는 ApiController의 전체 POST 방법이 여기에 포함됩니다 관심이있을 수 :

public async Task<HttpResponseMessage> Post(HttpRequestMessage request) 
    { 
     try 
     { 
      MetricCollector.RecordIncomingRecommendation(); 
      using (MetricCollector.TimeForwardingOfRequest()) 
      { 
       string requestContent = await request.Content.ReadAsStringAsync().ConfigureAwait(false); 
       var data = JObject.Parse(requestContent); 
       string payloadType = data.SelectToken("Headers.PayloadType").ToString(); 
       Log.Logger.Debug("Received message containing {PayloadType}", payloadType); 

       var consumersForPayloadType = _consumers.Where(x => x.DataTypes.Contains(payloadType)).ToList(); 
       if (consumersForPayloadType.Any()) 
       { 
        Log.Logger.Debug("{NumberOfConsumers} interested in {PayloadType}", 
         consumersForPayloadType.Count, 
         payloadType); 
       } 
       else 
       { 
        Log.Logger.Warning("No consumers are interested in {PayloadType}", payloadType); 
       } 

       foreach (var consumer in consumersForPayloadType) 
       { 
        try 
        { 
         var outgoingRequest = new HttpRequestMessage(HttpMethod.Post, consumer.Endpoint); 
         outgoingRequest.Content = new StringContent(requestContent, Encoding.UTF8, 
          "application/json"); 

         foreach (var header in request.Headers) 
         { 
          if (IsCustomHeader(header, _customHeaders)) 
           outgoingRequest.Headers.Add(header.Key, header.Value); 
         } 

         if (!string.IsNullOrWhiteSpace(consumer.ApiKey)) 
         { 
          request.Headers.Add("Authorization", "ApiKey " + consumer.ApiKey); 
         } 

         var response = await _httpClient.SendAsync(outgoingRequest); 
         if (!response.IsSuccessStatusCode) 
         { 
          Log.Logger.ForContext("HttpStatusCode", response.StatusCode.ToString()) 
           .Error("Failed to forward message containing {PayloadType} to {ConsumerEndpoint}", 
            payloadType, consumer.Endpoint); 
         } 
        } 
        catch (Exception ex) 
        { 
         MetricCollector.RecordException(ex); 
         Log.Logger.Error(ex, 
          "Failed to forward message containing {PayloadType} to {ConsumerEndpoint}", payloadType, 
          consumer.Endpoint); 
        } 
       } 

       return request.CreateResponse(HttpStatusCode.OK); 
      } 
     } 
     catch (Exception ex) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, ex); 
     } 
    } 

답변

0

사방 .ConfigureAwait(false)을 제거 시도하고 도움이되는지 확인합니다.

예. 여기 :

string requestContent = await request.Content.ReadAsStringAsync().ConfigureAwait(false); 

UPD1 : 좋아. 스트레스 테스트에 다른 클라이언트를 사용할 때 서버에서이 예외가 발생하는지 확인하십시오. 예 : this one. httpClient.SendAsync(...);을 기다리는 당신의 아이디어는 매우 독특합니다.

+0

불행히도, 아무런 차이가 없었습니다. 그러나 제안에 감사드립니다! – SabrinaMH