Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 让多个请求等待第一个请求完成(缓存)_C#_Asp.net_Caching - Fatal编程技术网

C# 让多个请求等待第一个请求完成(缓存)

C# 让多个请求等待第一个请求完成(缓存),c#,asp.net,caching,C#,Asp.net,Caching,我有一个web api,它有一些get方法,可以向多个运行时间很长且cpu昂贵的系统提出一些分布式查询。 所以我们加了一个。它就像一个符咒,在处理第一个查询后,速度相当快 所以现在,当释放缓存时,我遇到了一个(可能是常见的?)问题。 想象一下这样的场景:缓存失效或过期(出于某些好的原因),一次调用web api的不是一个客户端,而是100个客户端。当前发生的情况是,100个客户端开始运行长时间运行的查询,cpu爆炸到100%,服务器实例崩溃,不再响应。我基本上想要的是,只有第一个请求进行处理,让

我有一个web api,它有一些get方法,可以向多个运行时间很长且cpu昂贵的系统提出一些分布式查询。 所以我们加了一个。它就像一个符咒,在处理第一个查询后,速度相当快

所以现在,当释放缓存时,我遇到了一个(可能是常见的?)问题。 想象一下这样的场景:缓存失效或过期(出于某些好的原因),一次调用web api的不是一个客户端,而是100个客户端。当前发生的情况是,100个客户端开始运行长时间运行的查询,cpu爆炸到100%,服务器实例崩溃,不再响应。我基本上想要的是,只有第一个请求进行处理,让所有其他请求等待,直到他完成查询并将结果添加到缓存中。然后所有其他人都可以从缓存中获得响应

我知道有大约1000种方法可以实现这一目标,但我想知道是否有一种通用模式或最佳实践?或者我必须实施锁定?还是使用第三方物流?坦率地说,我不知道从哪里开始

事先非常感谢

编辑 除了下面非常好的答案之外,我还发现了这篇文章: 理想的方法是使用消息队列或服务总线。将任务排队,并在构建缓存时停止将其出列

这更容易处理,因为它只是暂停后台服务(例如,您可以从Windows服务实现消息队列/服务总线处理-您可能需要查看一下-)并恢复它

您的API应该将任务排队,而不是直接处理它们

可能的消息队列:

  • 。适用于简单的解决方案。它带有开箱即用的窗户
  • 。它也可以在本地基础上使用
在您的情况下,我会选择MSMQ方式,因为这是一个简单的场景,您只想让消息排队/退队

如果我在Web API相同的过程中需要它怎么办。。。
马蒂亚斯非常感谢您的回答和良好的建议。什么 如果我被迫走中间路线,你会怎么做 它与承载web api的过程相同吗

一个简单的解决方案可能是使用
ConcurrentQueue
模拟一个不太可靠的排队系统,并创建一个任务处理器线程,该线程可能在重建缓存时暂停或恢复


如果您在IIS上托管WebAPI,我会切换到在进程中托管它,也称为self-host。了解这篇文章

马蒂亚斯非常感谢您的回答和良好的建议。如果我被迫采用进程内的方式,那么你会提出什么建议?我非常感谢。我就是这么想的。你写这篇文章的动机是什么,你应该更好地使用self-host而不是iis?因为我在azure网站上运行,所以我想我不能这样做…@LaurinSt,因为IIS默认有空闲时间应用程序池重新链接策略,而且它从来没有被设计为承载长进程。。。在您的情况下,如果您在Azure中,为什么不将Web API托管在工作进程中?我仍然不知道如何使大量请求暂停并等待建立缓存值。如果您只是将从工作线程生成缓存项的请求排队,那么客户端在等待时会得到什么响应?它是如何生成的?@eniac您将在某个位置(即数据库)写入一些状态值(1:运行,2:成功),并且某个进程只能处理一个请求。另一方面,在进程运行时尝试获取值的请求可以用
100
状态代码(continue)响应。如果使用RabbitMQ或Azure Service Bus等消息队列代理,则可能需要保存一个进程标识符,以便在进程执行计算时,第一个请求和后续请求都可以接收具有该进程标识符的响应。