C# Owin中的最大并发请求数
我使用OWIN在控制台应用程序中自行托管一个小型web应用程序 在到达ApicController之前,注册了一个中间件:C# Owin中的最大并发请求数,c#,owin,self-hosting,httplistener,servicepointmanager,C#,Owin,Self Hosting,Httplistener,Servicepointmanager,我使用OWIN在控制台应用程序中自行托管一个小型web应用程序 在到达ApicController之前,注册了一个中间件: public class HealthcheckMiddleware : OwinMiddleware { private readonly string DeepHealthEndpointPath = "/monitoring/deep"; private readonly string ShallowHealthEndpointPath = "/mon
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
}
}
}
这里Next.Invoke调用控制器方法,该方法基本上是异步地将http请求转发给另一个API,即感兴趣的主线是:
var response = await _httpClient.SendAsync(outgoingRequest);
但是,如果我尝试像这样向API提交10个http请求(不是故意等待它们,因为我想对API进行预发行)
for(int i=0;i<10;i++)
{
var httpRequestMessage=新的httpRequestMessage(HttpMethod.Post,“http://localhost:5558/forwarder");
httpRequestMessage.Content=newStringContent(JsonConvert.SerializeObject(message),Encoding.UTF8,“application/json”);
httpClient.SendAsync(httpRequestMessage);
}
然后立即再提交10个,然后我在HealthcheckMiddleware中的catch块中得到以下异常:
InvalidOperationException:提交响应后无法执行此操作
堆栈跟踪:
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
位于System.Net.HttpListenerResponse.set_ContentLength64(Int64值)
位于Microsoft.Owin.Host.HttpListener.RequestProcessing.ResponseHeadersDictionary.Set(字符串头,字符串值)
位于Microsoft.Owin.Host.HttpListener.RequestProcessing.HeadersDictionaryBase.Set(字符串键,字符串[]值)
位于Microsoft.Owin.Host.HttpListener.RequestProcessing.HeadersDictionaryBase.set_项(字符串键,字符串[]值)
位于Microsoft.Owin.HeaderDictionary.System.Collections.Generic.IDictionary.set_项(字符串键,字符串[]值)
位于System.Web.Http.Owin.HttpMessageHandlerAdapter.SetHeadersForEmptyResponse(IDictionary`2头)
在System.Web.Http.Owin.HttpMessageHandlerAdapter.SendResponseMessageAsync(HttpRequestMessage请求、HttpResponseMessageResponse、IOwinResponse owinResponse、CancellationToken CancellationToken)
在System.Web.Http.Owin.HttpMessageHandlerAdapter.d_u0.MoveNext()中
---来自引发异常的上一个位置的堆栈结束跟踪---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)
在System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务任务)中
在System.Runtime.CompilerServices.TaskAwaiter.GetResult()中
在C:\\ u code\DataRelay.nonguarantedDataForwarder\HealthcheckMiddleware.d\\ u 3.MoveNext()中的DataRelay.nonguarantedDataForwarder.HealthcheckMiddleware.cs:第30行
我尝试搜索Stackoverflow和Google,但似乎找不到任何有价值的东西。例如,我发现,但在这里,开发人员在提交请求后读取请求,而我没有这样做
为了以防万一,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);
}
}
公共异步任务Post(HttpRequestMessage请求)
{
尝试
{
MetricCollector.RecordIncomingRecommension();
使用(MetricCollector.TimeForwardingFrequest())
{
string requestContent=await request.Content.ReadAsStringAsync().ConfigureAwait(false);
var data=JObject.Parse(requestContent);
字符串payloadType=data.SelectToken(“Headers.payloadType”).ToString();
Debug(“收到的消息包含{PayloadType}”,PayloadType);
var consumersForPayloadType=_consumers.Where(x=>x.DataTypes.Contains(payloadType)).ToList();
if(consumersForPayloadType.Any())
{
Log.Logger.Debug(“{NumberOfConsumers}对{PayloadType}感兴趣”,
Consumers ForPayloadType.Count,
有效载荷类型);
}
其他的
{
警告(“没有消费者对{PayloadType}”感兴趣”,PayloadType);
}
foreach(consumersForPayloadType中的var使用者)
{
尝试
{
var outgoingRequest=newhttprequestmessage(HttpMethod.Post,consumer.Endpoint);
outgoingRequest.Content=新的StringContent(requestContent,Encoding.UTF8,
“应用程序/json”);
foreach(request.Headers中的var头)
{
if(IsCustomHeader(header,_customHeaders))
outgoingRequest.Headers.Add(header.Key,header.Value);
}
如果(!string.IsNullOrWhiteSpace(consumer.ApiKey))
{
添加(“授权”、“ApiKey”+消费者.ApiKey);
}
var response=await\u httpClient.sendsync(outgoingRequest);
如果(!response.issucessStatusCode)
{
Log.Logger.ForContext(“HttpStatusCode”,response.StatusCode.ToString())
.Error(“无法将包含{PayloadType}的消息转发到{ConsumerEndpoint}”,
payloadType,consumer.Endpoint);
}
}
捕获(例外情况除外)
{
MetricCollector.RecordException(ex);
Log.Logger.Error(例如,
“无法将包含{PayloadType}的消息转发到{ConsumerEndpoint}”,PayloadType,
消费者(端点);
}
}
返回request.CreateResponse(HttpStatusCode.OK);
}
}
捕获(例外情况除外)
{
返回请求.CreateErrorResponse(HttpStatusCode.ServiceUnavailable,ex);
}
}
尝试删除
.configurewait(false)
所有位置,看看是否有帮助
例如,这里:
string requestContent = await request.Content.ReadAsStringAsync().ConfigureAwait(false);
UPD1:好的。
string requestContent = await request.Content.ReadAsStringAsync().ConfigureAwait(false);