ruby-on-rails - 如何更改这些生产者-消费者微服务以允许并行处理?

标签 ruby-on-rails ruby multithreading parallel-processing microservices

我有几个微服务(用 ruby​​ 实现,尽管我怀疑这对我的问题是否重要)。其中一个提供项目,另一个处理它们,然后将它们标记为已处理(通过 DELETE 调用)

提供者有一个 /items 端点,它以 JSON 格式列出了一堆用 id 标识的项目。它还有一个 DELETE/items/id 端点,它从列表中删除一个项目(大概是因为它已被处理)

“处理器”中的代码(非常简化)如下所示:

items = <GET provider/items>
items.each do |item|
  process item
  <DELETE provider/items/#{item.id}>
end

这有几个问题,但我想解决的一个问题是它不是线程安全的,因此我不能并行运行它。如果两个工作人员同时开始处理项目,他们将“踩到对方的脚趾”:他们将获得相同的项目列表,然后(尝试)处理和删除每个项目两次。

更改此设置以允许并行处理的最简单方法是什么?

您可以假设我有 ruby​​ 可用。我宁愿将更改保持在最低限度,并且如果可能的话宁愿不安装其他 gem。 Sidekiq可作为消费者上的排队系统使用。

最佳答案

一些备选方案(只是集思广益):

  1. 只需放弃 HTTP 并使用带有队列的发布-订阅。让生产者排队,一些消费者处理它们(并触发状态变化,如果你喜欢的话,在这种情况下使用 HTTP)。
  2. 如果您真的想要 HTTP,我认为还有一些遗漏的地方。如果您的项目的状态是pendingprocessed,则您的状态机中存在隐藏/隐式状态:in_progress(或其他)。一旦您想到它,情况就会变得更加清晰:您的 GET/items 不是幂等的(因为它将项目的状态从待处理更改为进行中),因此首先不应该是 GET。

    一个。另一种方法是添加一个新实体(例如批处理),该实体通过 POST 创建并将一些项目分组并发送。已经退回的项目不会成为 future 批处理的一部分,然后您可以将整个批处理标记为已完成(例如 PUT/batches/X/done)。这很快就会变得疯狂,因为您将开始重新实现队列系统和普通/显式(参见 c)HTTP 中已经存在的特性(确认、超时、错误)。

    一个稍微简单的替代方案:只需在 POST/PUT (两种情况下都很奇怪)端点中将 /items 标记为正在处理的项目(和不再返回它们,因为它只返回待处理的项目)。但是,错误和超时也存在同样的问题。

    让生产者明确并通过 PUT 向其他服务请求处理项目。您可以在正文中包含所有需要的数据,或者将其用作 ping 并让处理器通过 GET 请求信息。您可以在任一侧添加异步处理(但在处理器中可能更好)。

我会诚实地做 1(除非有令人信服的理由)。

关于ruby-on-rails - 如何更改这些生产者-消费者微服务以允许并行处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27839789/

相关文章:

ruby-on-rails - 在PaperTrail中,如何记录每个版本的评论?

ruby-on-rails - PHP 的 Ruby APC 模拟?

java - 意外的并发修改异常

java - 如何在Red5中创建线程?

ruby-on-rails - Rails3 路由问题 : undefined method `resources'

mysql - Rails & Mysql - 优化和改写查询

ruby-on-rails - 如果记录存在,Rails 如何改进?

javascript - rails : redirect_to:back not redirecting in spite of showing correct logs

ruby-on-rails - OmniContacts gem 总是无法访问我的雅虎联系人导入

java - Java 中的 Runtime.exec() 挂起,因为它正在等待来自 System.in 的输入