我有一个 web api,它有一些 get 方法,可以向多个运行时间很长且 cpu 昂贵的系统提出一些分布式查询。 所以我们添加了一个 output caching .工作起来很有魅力,在处理完第一个查询后速度非常快。
所以现在我在释放缓存时遇到了一个(也许是常见的?)问题。 想象一下缓存失效或过期(出于某些充分的原因)并且不是一个客户端一次调用 web api 而是 100 个客户端的场景。当前发生的情况是 100 个客户端开始运行长时间运行的查询并且 cpu 爆炸到 100%,服务器实例崩溃并且不再响应。我基本上想要的是只有第一个请求进行处理并让所有其他请求等到他完成查询并将结果添加到缓存中。然后所有其他的都可以从缓存中获取响应。
我知道有大约 1,000 种方法可以实现它,但我想知道是否有通用模式或最佳实践?还是我必须实现锁?或者使用 TPL 或什么?坦率地说,我不知道从哪里开始?
非常感谢您。
编辑 除了下面很好的答案外,我还找到了这篇文章: http://www.asp.net/aspnet/overview/developing-apps-with-windows-azure/building-real-world-cloud-apps-with-windows-azure/queue-centric-work-pattern
最佳答案
理想的方式 是使用消息队列或服务总线。将您的任务入队并在构建缓存时停止将它们出队。
这更容易处理,因为它只是暂停后台服务(例如,您可以从 Windows 服务实现消息队列/服务总线处理 - 您可能想看一下 at Topshelf这个 -) 并恢复它。
您的 API 应该将任务排入队列,而不是直接处理它们。
可能的消息队列:
- MSMQ .适用于简单的解决方案。它随 Windows 一起提供,开箱即用。
- RabbitMQ .
- Azure Service Bus .它也可以在本地使用 with Azure Pack .
- NServiceBus
在你的情况下,我会采用 MSMQ 方式,因为这是一个简单的场景,你只想对消息进行入队/出队......
如果我在与 Web API 相同的进程中需要它怎么办...
Matias thank you very much for your answer and the good proposal. What way would you propose if i am forced to go a inprocess way, so doing it in the same process as the web api is hosted?
一个简单的解决方案可能是使用 ConcurrentQueue<T>
模拟一个不太可靠的排队系统。并创建一个任务处理器线程,它可能会在重建缓存时暂停或恢复。
如果您在 IIS 上托管您的 WebAPI,我会切换到在进程中托管它,也称为 self-host。了解此阅读 this WebAPI OWIN/Katana self-host tutorial .
关于c# - 让多个请求等待第一个完成(缓存),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32778174/