微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – 如何部署线程安全的异步Rails应用程序?

我已经在网上阅读了大量关于不同版本的 ruby和rails中的线程安全性和性能的材料,我想我现在对这些事情了如指掌.

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

>利用所有cpu内核,最小化RAM使用率
>能够在先前的请求等待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,每秒可以服务数百或数千个请求,而且必须通过网络发送请求,等待工作完成,然后通过网络接收答案,因此比快速慢得多.

因此,理想的部署将允许数百个请求快速完成,而请求缓慢等待IO.

围绕Web的讨论似乎缺少的是堆栈的哪一层负责实现这种并发. thin有一个–threaded标志,它将“在线程中调用机架应用程序[实验]” – 是否为每个传入请求启动一个新线程?在持续存在并等待传入​​请求的线程中假装机架应用程序实例?

瘦是唯一的方式还是其他人? ruby运行时是否对优化第2点很重要?

解决方法

适合您的方法在很大程度上取决于您的慢速方法.

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

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

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

另请参阅CrampGoliath.这些允许您在与Rails应用程序一起托管的单独Rack应用程序中实现慢速方法,但您可能还必须重写代码以在Cramp / Goliath处理程序中工作.

至于你关于Ruby运行时的问题,它还取决于缓慢的工作.如果你正在进行cpu大量计算,那么你冒着GIL的风险给你带来问题.如果您正在进行IO,那么GIL不应该妨碍您. (我说不应该因为我相信我已经阅读了关于阻止GIL的旧MysqL gem的问题.)

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

原文地址:https://www.jb51.cc/ruby/270063.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐