您可以使用threads https://ruby-doc.org/core-2.2.0/Thread.html为了这。
这是一个简单的解决方案:
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 中使用并发时需要注意一些事情。首先也是最重要的是,当您使用线程时,您将面临并发带来的所有复杂情况。期待头痛。并发可以很快地混淆简单的任务。例如,对于您的问题,您需要确保您的三个任务是真正独立。一项任务是否依赖于另一项任务的输出?一个有副作用吗?比如说,是否将一些数据写入后续作业所依赖的数据库?如果是这种情况,那么上述方法将不起作用,您需要弄清楚如何适应它们特定的相互依赖关系。
其次,红宝石线程是绿线 https://en.wikipedia.org/wiki/Green_threads。 (假设您使用的是 MRI Ruby,而不是 Rubinius 或 JRuby。)这意味着您只能使用 Ruby 线程来完成某些任务。幸运的是,网络请求是所做的事情之一not阻塞 ruby 线程,意思是上面的解决方案will同时发出所有请求。您应该会看到此解决方案的加速效果。
最后,这在某种程度上特定于您的用例,当您的应用程序调用第三方时,通常最佳实践是将这些内容委托给工作人员。对第三方的调用很容易出错,并且向客户端返回 400 秒(如果您不小心处理错误,则返回 500 秒!) 很糟糕。最好将该工作放入队列中,并向客户端提供一个响应,该响应本质上是“收到请求,稍后再做”。
鉴于这一切,如果您发现需要比本机 ruby 线程更强大的东西,请查看并发 ruby https://github.com/ruby-concurrency/concurrent-ruby gem.
@AbM 的回答提到了 Resque/DJ。如需更通用的解决方案,请查看活跃工作 http://edgeguides.rubyonrails.org/active_job_basics.html。对于某些(但不是全部)变体,请参阅ActiveJob 适配器列表 http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html.