【问题标题】:How to deploy a threadsafe asynchronous Rails app?如何部署线程安全的异步 Rails 应用程序?
【发布时间】:2011-12-30 02:49:08
【问题描述】:

我在网上阅读了大量关于不同版本的 ruby​​ 和 rails 中线程安全和性能的资料,我认为我现在非常了解这些内容。

讨论中似乎奇怪地遗漏了如何实际部署异步 Rails 应用程序。在谈论应用程序中的线程和同步性时,人们想要优化两件事:

  1. 以最少的 RAM 使用率利用所有 CPU 内核
  2. 能够在之前的请求等待 IO 时处理新请求

第 1 点是人们(正确地)对 JRuby 感到兴奋的地方。对于这个问题,我只是想优化第 2 点。

假设这是我的应用程序中唯一的控制器:

TheController < ActionController::Base
  def fast
    render :text => "hello"
  end

  def slow
    render :text => User.count.to_s
  end
end

fast 没有 IO,每秒可以处理成百上千个请求,而 slow 必须通过网络发送请求,等待工作完成,然后通过网络接收应答,并且是因此比fast慢得多。

因此,理想的部署将允许满足对fast 的数百个请求,而对slow 的请求正在等待IO。

围绕网络的讨论似乎缺少的是堆栈的哪一层负责启用这种并发性。 Thin 有一个 --threaded 标志,它将“在线程中调用 Rack 应用程序 [实验性]”——这是否会为每个传入请求启动一个新线程?在持续等待传入请求的线程中处理机架应用实例?

瘦是唯一的方法还是有其他方法? ruby 运行时对于优化点 2 是否重要?

【问题讨论】:

  • 我怀疑你的 ruby​​ 版本对第 2 点有太多发言权。这将更多地取决于服务器的并发实现以及 rails 本身的组合方式。

标签: ruby-on-rails ruby multithreading rack thin


【解决方案1】:

适合您的方法在很大程度上取决于您的 slow 方法在做什么。

在一个完美的世界中,您可以使用类似sinatra-synchrony gem 的东西来处理纤程中的每个请求。您只会受到最大光纤数量的限制。不幸的是,光纤上的堆栈大小为hardcoded,并且在 Rails 应用程序中很容易溢出。此外,我读过一些关于调试纤程困难的恐怖故事,因为异步 IO 启动后会自动屈服。使用光纤时仍然可能出现竞争条件。目前,纤维化的 Ruby 有点像贫民窟,至少在 Web 应用程序的前端是这样。

不需要更改代码的更实用的解决方案是使用具有工作线程池的 Rack 服务器,例如 Rainbows!或彪马。我相信 Thin 的 --threaded 标志会在新线程中处理每个请求,但启动本机操作系统线程并不便宜。最好使用池大小设置得足够高的线程池。在 Rails 中,不要忘记在生产环境中设置 config.threadsafe!

如果您可以更改代码,您可以查看 Konstantin Haase 的出色 talk on real-time Rack。他讨论了使用EventMachine::Deferrable 类在构建 Rack 的传统请求/响应周期之外产生响应。这看起来很简洁,但是您必须以异步样式重写代码。

还可以查看CrampGoliath。这些允许您在与 Rails 应用程序一起托管的单独 Rack 应用程序中实现 slow 方法,但您可能还必须重写代码才能在 Cramp/Goliath 处理程序中工作。

至于您关于 Ruby 运行时的问题,这也取决于 slow 所做的工作。如果您正在执行 CPU 密集型计算,那么您将面临 GIL 给您带来问题的风险。如果你在做 IO,那么 GIL 不应该 妨碍你。 (我说不应该,因为我相信我已经阅读过有关阻止 GIL 的旧 mysql gem 的问题。)

就我个人而言,我已经成功地将 sinatra-synchrony 用于后端 mashup Web 服务。我可以并行向外部 Web 服务发出多个请求,然后等待所有请求返回。同时,前端 Rails 服务器使用线程池,直接向后端发出请求。不完美,但目前运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 2021-11-06
    • 2015-08-11
    • 2011-07-04
    • 2016-10-10
    • 2011-02-13
    相关资源
    最近更新 更多