该方法查询和聚合来自第三方API的结果,如果发出太多请求,该API可能会失控。
我考虑的方法是在Autofac中将控制器注册为单例,并使用锁来管理字段级变量的状态,该变量跟踪方法是否已经在进行中。
这是一个干净的实现还是它包含bug/竞争条件?
public class ExpensiveController : Controller
{
private bool _alreadyRunning = false;
private static readonly object Instancelock = new object();
[HttpGet("expensiveController/CallThirdPartyApi")]
public ActionResult<IEnumerable<MyObject>> CallThirdPartyApi()
{
// Critical Section Start
lock (Instancelock)
{
if (_alreadyRunning == true)
{
return Ok
}
else
{
_alreadyRunning = true;
}
} //Critical Section End
// do work
var list = DoExpensiveProcessing()
_alreadyRunning = false;
return list;
}
}
字符串
下面是代码的清理版本,它使用一个静态字段来跟踪状态,而不是扰乱控制器的生命周期。
public class ExpensiveController : Controller
{
private static bool _alreadyRunning;
private static readonly object InstanceLock = new object();
[HttpGet("expensiveController/CallThirdPartyApi")]
public ActionResult<IEnumerable<MyObject>> CallThirdPartyApi()
{
lock (InstanceLock)
{
if (_alreadyRunning)
{
return new ServiceUnavailableResult();
}
_alreadyRunning = true;
}
var list = DoExpensiveProcessing()
lock (InstanceLock)
{
_alreadyRunning = false;
}
return list;
}
}
}
型
2条答案
按热度按时间jslywgbw1#
一个简单的版本可以是
字符串
3xiyfsfu2#
我创建了一个库,可以帮助你实现你的目标。它叫做AsyncKeyedLock,可以通过NuGet获得。如果你使用DI注入一个
AsyncKeyedLocker<string>
单例,你就可以通过键锁定,其中键是控制器的名称。这样你就可以控制你想要对每个控制器进行多少并发调用。