multithreading - ASP.net Web API 中的异步线程
问题描述
我必须更新调用 AWS 中托管的第三方 API 的数千个 SKU 的价格。第三方的 TPS 限制为 1000,即每秒允许 1000 次 API 调用。第三方 API 每次调用 API 大约需要 1.5 秒。
现在每次如果我通过调用第三方 API 顺序更新价格,对于 2,000 种产品,价格更新需要 2000 * 1.5 = 3000 秒。通过使用线程和线程同步,这应该在 3 秒内实现,因为 TPS 油门是 1000。这是我当前方法的示例代码片段:
[HttpPut]
public async Task<HttpResponseMessage> UpdatePrices([FromBody] List<PriceViewModel> prices)
{
int failedAPICalls = 0;
int successAPICalls = 0;
foreach (var p in prices) {
PriceManagement pm = new PriceManagement();
ErrorViewModel error = await pm.UpdateMarketplacePrice(p.SKU, p.Price);
if (error != null) {
failedAPICalls++;
//Error handling code here...
}
else {
successAPICalls++;
//Log price update to database
}
}
var totalApiCalls = successAPICalls + failedAPICalls;
string message = "Total API calls : " + totalApiCalls.ToString() + " | Successfull API Calls: " + successAPICalls.ToString()
+ " | Failed API Calls: " + failedAPICalls.ToString();
return Request.CreateResponse(HttpStatusCode.OK, message);
}
这是示例定义视图模型:
public class PriceViewModel
{
public string SKU { get; set; }
public decimal Price { get; set; }
}
public class ErrorViewModel
{
public int StatusCode { get; set; }
public string Description { get; set; }
}
请帮助我提高性能。
解决方案
您发布的代码是顺序的。异步但仍然是顺序的。await
在继续执行之前,将等待已经异步操作完成而不阻塞。它不会同时触发所有请求。
使用特定限制进行多个并发调用的一种简单方法是使用ActionBlock<>并将其MaxDegreeOfParallelism
设置为您想要的限制,例如:
var options=new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = maxDegreeOfParallelism,
BoundedCapacity = capacity
};
var block=new ActionBlock<PriceViewModel>(async p=>{
var pm = new PriceManagement();
var error = await pm.UpdateMarketplacePrice(p.SKU, p.Price);
if (error != null) {
Interlocked.Increment(ref failedAPICalls);
}
else {
Interlocked.Increment(ref successAPICalls);
}
}, options);
设置MaxDegreeOfParallelism
控制可以同时处理的消息数量。其余消息被缓冲。
创建块后,我们可以向其发布消息。每条消息将由一个单独的任务处理,最高可达 MaxDOP 限制。完成后,我们告诉该块并等待它完成所有剩余的消息。
foreach(var p in prices)
{
await block.SendAsync(p);
}
//Tell the block we're done
block.Complete();
//Wait until all prices are processed
await block.Completion;
默认情况下,可以缓冲的项目数量没有限制。如果操作缓慢,这可能是一个问题,因为缓冲区可能最终会出现数千个等待处理的项目,基本上是重复价格表。
为避免这种情况,BoundedCapacity
可以设置为特定的数字。达到限制时SendAsync
将阻塞,直到插槽可用
推荐阅读
- python - 将背景图像添加到 Seaborn 散点图
- common-lisp - 什么是“真正的”功能?
- ssl - 将两个 .crt 和一个 .key 文件转换为 .pem
- android - 使用图层列表以编程方式更改 Drawable 中形状的颜色?
- c# - 做model.GetDeclaredSymbol时如何获取SynthesizedIntrinsicOperatorSymbol而不是SourceUserDefinedOperatorSymbol
- javascript - 使用 Node 创建目录和提取 HTML 标签
- javascript - 使用 javascript 填充 html 表
- python - 来自不同数据集的节点属性
- haskell - Haskell - 我如何在 IO 函数中使用 Maybe
- asp.net-core - 如何将用户声明从专用身份 API 传递到 ASP.NET 核心中的内部 API?