C# 当轻负载应用于.Net核心Web Api时,请求超时
我有一个API,它基本上接收一个请求并将其推送到一个SQS队列,并不复杂C# 当轻负载应用于.Net核心Web Api时,请求超时,c#,asp.net-core,amazon-ecs,C#,Asp.net Core,Amazon Ecs,我有一个API,它基本上接收一个请求并将其推送到一个SQS队列,并不复杂 [HttpPost] public ActionResult Post([FromBody]object message, [FromHeader] string source) { if (message== null) return new UnsupportedMediaTypeResult(); if (PublishMessageToSQS(Json
[HttpPost]
public ActionResult Post([FromBody]object message, [FromHeader] string source)
{
if (message== null)
return new UnsupportedMediaTypeResult();
if (PublishMessageToSQS(JsonConvert.SerializeObject(message),source))
return StatusCode(201);
return StatusCode(500);
}
private bool PublishMessage(string message, string source)
{
try
{
RetryWhenException.Do(
() =>
{
SendMessageRequest request = new SendMessageRequest()
{
MessageBody = message,
MessageAttributes = new Dictionary<string, MessageAttributeValue>(),
QueueUrl = "my queue",
};
if (!string.IsNullOrEmpty(source))
request.MessageAttributes.Add("source", new MessageAttributeValue()
{
StringValue = source,
DataType = "String"
});
var result = sqsClient.SendMessageAsync(request).Result;
}, 3, 1000);
return true;
}
catch (Exception e)
{
//log
throw;
}
}
[HttpPost]
公共操作结果帖子([FromBody]对象消息,[FromHeader]字符串源)
{
如果(消息==null)
返回新的不受支持的MediaTypeResult();
if(PublishMessageToSQS(JsonConvert.SerializeObject(消息),源))
返回状态码(201);
返回状态码(500);
}
私有bool PublishMessage(字符串消息,字符串源)
{
尝试
{
RetryWhenException.Do(
() =>
{
SendMessageRequest=新建SendMessageRequest()
{
MessageBody=消息,
MessageAttributes=新字典(),
QueueUrl=“我的队列”,
};
如果(!string.IsNullOrEmpty(源))
request.MessageAttributes.Add(“source”,newmessageattributevalue())
{
StringValue=源,
DataType=“String”
});
var result=sqsClient.SendMessageAsync(请求).result;
}, 3, 1000);
返回true;
}
捕获(例外e)
{
//日志
投掷;
}
}
此API是容器化的,并部署到低资源机器(0.25 VCpu,512 MB RAM)上的AWS ECS
在API上应用轻负载(每秒10个请求)时,请求在一段时间后开始超时
在应用以下其中一项时,我停止接收超时:
1-使用更多资源(2个VCPU、4GB RAM)
2-使我的操作异步
[HttpPost]
public async Task<ActionResult> Post([FromBody]object message, [FromHeader] string source)
{
if (message== null)
return new UnsupportedMediaTypeResult();
if (await PublishMessageToSQS(JsonConvert.SerializeObject(message), source))
return StatusCode(201);
return StatusCode(500);
}
private async Task<bool> PublishMessage(string message, string source)
{
try
{
await RetryWhenException.Do(
async () =>
{
SendMessageRequest request = new SendMessageRequest()
{
MessageBody = message,
MessageAttributes = new Dictionary<string, MessageAttributeValue>(),
QueueUrl = "my queue",
};
if (!string.IsNullOrEmpty(source))
request.MessageAttributes.Add("source", new MessageAttributeValue()
{
StringValue = source,
DataType = "String"
});
var result = await sqsClient.SendMessageAsync(request);
}, 3, 1000);
return true;
}
catch (Exception e)
{
//log
throw;
}
}
[HttpPost]
公共异步任务发布([FromBody]对象消息,[FromHeader]字符串源)
{
如果(消息==null)
返回新的不受支持的MediaTypeResult();
if(等待PublishMessageToSQS(JsonConvert.SerializeObject(消息),源))
返回状态码(201);
返回状态码(500);
}
专用异步任务PublishMessage(字符串消息,字符串源)
{
尝试
{
等待重新接收。是否执行(
异步()=>
{
SendMessageRequest=新建SendMessageRequest()
{
MessageBody=消息,
MessageAttributes=新字典(),
QueueUrl=“我的队列”,
};
如果(!string.IsNullOrEmpty(源))
request.MessageAttributes.Add(“source”,newmessageattributevalue())
{
StringValue=源,
DataType=“String”
});
var result=wait sqsClient.SendMessageAsync(请求);
}, 3, 1000);
返回true;
}
捕获(例外e)
{
//日志
投掷;
}
}
RetryWhenException代码:
public static class RetryWhenException
{
public static void Do(Action action, int maxAttemptCount = 3, int retryInterval = 1000)
{
var exceptions = new List<Exception>();
for (var attempted = 0; attempted < maxAttemptCount; attempted++)
{
try
{
if (attempted > 0)
{
Thread.Sleep(retryInterval);
}
action();
return;
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
throw new AggregateException(exceptions);
}
}
公共静态类RetryWhenException
{
公共静态void Do(Action-Action,int-maxAttemptCount=3,int-retryInterval=1000)
{
var exceptions=新列表();
对于(var尝试=0;尝试0)
{
睡眠(重试区间);
}
动作();
返回;
}
捕获(例外情况除外)
{
例外情况。添加(ex);
}
}
抛出新的AggregateException(异常);
}
}
我知道异步可以释放线程,但是推送到SQS并没有那么昂贵,请求的数量也没有那么高
我真的不明白为什么我在应用如此低的负载时会超时,为什么异步会这样做,有什么解释吗?我可以想象
PublishMessageToSQS
正在阻塞,它的异步变体将释放线程并在完成后立即返回。为了验证您是否需要与我们共享PublishMessageToSQS
的代码。@二十个问题已更新,我知道旧版本的代码被阻塞,但我认为.Net core已为每个请求启动一个新线程。AFAIK ASP.Net core不会为每个请求启动一个新线程。相反,所有请求都由专用线程池处理(其线程数由KestrelServerOptions.ThreadCount控制,默认为处理器数的一半),并且不能保证每个请求都由单个线程提供服务。因此,任何长时间运行的同步I/O都会很快耗尽线程池。更多信息