首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Rails在控制器中异步执行任务

Rails在控制器中异步执行任务
EN

Stack Overflow用户
提问于 2017-03-22 20:25:52
回答 1查看 10.2K关注 0票数 2

当我的Controller中的路由被调用时,我需要完成三个任务。现在,我的代码看起来像这样(经过简化):

代码语言:javascript
运行
复制
 def set_quotas

    TaskOne.new().ex
    TaskTwo.new().ex
    TaskThree.new().ex

    quotas = @user.quotas
    render json: quotas, status: 200, each_serializer: Api::V1::QuotaSerializer
  end

每个任务都按顺序运行。但是,它们中的几个调用外部服务。因此,完成此调用所需的总时间最终是4-8秒,我们真的希望加快速度。

我想要做的是同时运行这三个任务,但要等到每个任务都完成后才能呈现json响应。在Rails中实现这一点的最好方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-23 06:36:01

您可以使用threads来实现这一点。

这里有一个简单的解决方案:

代码语言:javascript
运行
复制
def set_quotas
  [
    Thread.new { TaskOne.new().ex },
    Thread.new { TaskTwo.new().ex },
    Thread.new { TaskThree.new().ex }
  ].each &:join

  quotas = @user.quotas
  render json: quotas, status: 200, each_serializer: Api::V1::QuotaSerializer
end

然而,在Ruby中使用并发时,有几件事需要注意。首先,也是最重要的是,当您使用线程时,您将受到并发带来的所有复杂性的影响。预计会令人头痛。并发可以非常快地混淆简单的任务。例如,对于您的问题,您需要确保您的三个任务是真正独立的。一个任务依赖于另一个任务的输出吗?有副作用吗?例如,是否将一些数据写入后续作业所依赖的数据库中?如果是这种情况,那么上述方法将不起作用,您需要弄清楚如何适应它们特定的相互依赖关系。

其次,ruby线程是green threads的。(假设您使用的是MRI Ruby,而不是Rubinius或JRuby。)这意味着如果你只想通过ruby线程来完成某些任务的加速。幸运的是,web请求是不会阻塞ruby线程的事情之一,这意味着上面的解决方案将并发地发出所有请求。您应该会看到此解决方案的加速效果。

最后,这在某种程度上是特定于您的用例的,当您的应用程序向第三方发出调用时,通常最佳实践是将这些东西降级给工作人员。对第三方的调用很容易出错,而且返回400秒(500秒,如果你不小心处理错误的话!)给客户。最好是将该工作放入队列中,并给客户端一个响应,本质上是“收到请求,稍后再做”。

考虑到这一切,如果您发现需要比原生ruby线程更强大的东西,请查看concurrent-ruby gem。

@AbM的答案提到了Resque/DJ。有关更一般的解决方案,请查看ActiveJob。对于某些(但不是所有)变体,请参阅ActiveJob adapter list

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42951615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档