http - Golang 检测飞行中的请求

标签 http caching concurrency go request

我想知道是否已经有一个库可以做到这一点,或者是否有建议可以解决以下问题:

客户端 A 请求资源 A,这是一个长时间运行的请求,因为资源 A 很昂贵并且会导致缓存未命中。与此同时,客户端 B 请求资源 A,现在它仍然是缓存未命中,因为客户端 A 的请求尚未返回并填充缓存。因此,与其发出新的请求来生成资源 A,客户端 B 应该阻止并在客户端 A 的请求完成并填充缓存时得到通知。

我认为组缓存库有类似的东西,但我无法浏览代码以弄清楚它们是如何做到的,我也不想将实现绑定(bind)到它并将它用作一个依赖。

到目前为止,我唯一的解决方案是发布-订阅类型的东西,我们有一个当前飞行请求的全局映射,以 reqID 作为键。当 req1 到来时,它在 map 中设置它的 ID,req2 到来并检查它的 id 是否在 map 中,因为它请求的是相同的资源,所以我们在通知 channel 上阻塞。当 req1 完成时,它会做 3 件事:

  1. 从 map 中移除其 ID
  2. 将条目保存在缓存中
  3. 向通知者 channel 发送一个带有其 ID 的广播 req2 收到通知,解除阻塞并从缓存中获取。

因为 go 没有内置对广播的支持,所以可能有 1 个灌浆监听广播 channel ,然后为每个请求保留一个订阅者列表,或者我们将映射更改为 reqId => list(广播 channel 订阅者)。类似的东西。

如果您认为使用 Go 的基元有更好的方法,欢迎任何意见。这个解决方案中唯一困扰我的是这个全局 map ,被锁包围着,我认为它很快就会成为瓶颈。如果您有一些非锁定的想法,即使它们是概率性的,我也很乐意听到它们。

最佳答案

这让我想起了一个有人在实现类似事情的问题:

Coalescing items in channel

我用实现这样一个中间层的例子给出了答案。我认为这符合您的想法:有一个例行程序来跟踪对同一资源的请求,并防止它们被并行重新计算。

如果您有一个单独的例程负责接受请求和管理对缓存的访问,则您不需要显式锁(虽然有一个隐藏在 channel 中)。无论如何,我不知道您的应用程序的具体情况,但考虑到您需要检查缓存(可能已锁定)和(偶尔)对丢失的条目执行昂贵的计算——锁定 map 查找对我来说似乎不是一个大问题。如果您认为这会有所帮助,您也可以始终跨越更多此类中间层例程,但您需要一种确定性的方式来路由请求(因此每个缓存条目都由一个例程管理)。

很抱歉没有为您提供银弹解决方案,但听起来您已经找到了解决问题的好方法。

关于http - Golang 检测飞行中的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31091139/

相关文章:

php - 无法访问 PHP 基本身份验证变量

java - 如何制作联系人 ListView ?

caching - 使用 nginx 直接从 redis 缓存中提供内容

java - 编写一个包含整数的 ArrayList,该整数将被并发访问

c++ - 如何将带有参数的方法传递给线程以执行?

concurrency - Actor 模型中的仲裁者如何在 Erlang 中实现?

http - 在 Racket 中解压 gzipped html

python - 在 python 3 中从 http 打开图像

c# - Azure Service Fabric 中的节点之间广播消息

mysql - rails + 亚马逊 RDS : latency issues