Ruby的多线程应用服务器介绍

随着Rails4.0的发布,Ruby的Web开发社区开始进入多线程的时代了: nginx

  1. 从Ruby1.9开始,多线程已是native thread了,尽管有GIL全局锁的存在,可是对于IO并发来讲,已经能够实现并行处理了。
  2. Rails4.0开始,默认打开了多线程运行模式,将推进整个Ruby的Web开发社区迁移到多线程Web模式。

多线程服务器的模型,相比传统多进程服务器模型,能够很是有效的提升IO并发的吞吐量。我如今开发Web应用,已经所有改用多线程了,我写过一个相关的文档介绍:Web并发模型粗浅探讨,有哪些Ruby的应用服务器能够良好的支持多线程呢? git

Rainbows

rainbowsunicorn是同一个做者Eric Wong开发的,rainbows和unicorn很是像,他们之间的主要区别就是:unicorn是多进程服务器,rainbows是多线程服务器,此外基本用法,配置都同样的,自己rainbows就是基于unicorn开发的。 github

unicorn如今被普遍的使用在不少负载很是高的生产环境中,rainbows也和unicorn一样很是稳定。因为Ruby1.9的GIL,多线程并发只能有效使用1颗CPU内核,所以在多核服务器上,须要运行多个rainbows进程。通常来讲,服务器有多少CPU内核,就启动多少个rainbows worker进程。每一个rainbows进程里面再启动多个线程,所以理想状况下,可以同时处理的IO并发请求数量等于 “进程数” × “线程数”,看一个例子: web

rainbows.rb,注意如下3项配置: shell

use :ThreadPool # 使用线程池模式,进程启动的时候建立好线程数 worker_processes 4 # 建立多少个进程 worker_connections 64 # 每一个进程建立多少个线程

以上面的配置为例,若是你在一台4核服务器上面部署应用,但愿尽可能使用服务器资源,那么能够建立4个进程,每一个进程建立64个线程,所以整个服务器IO并发处理能力是256个执行线程,这比传统的多进程模式要高得多。 ruby

控制rainbows服务器的shell脚本很容易写:rainbows.sh,rainbows和unicorn同样,都是经过给进程发送信号来控制服务器的。 服务器

以上的配置启动之后,会有5个rainbows进程:1个master控制进程,4个worker工做进程。master进程负责加载应用程序代码,建立和销毁worker进程,分发请求;worker进程负责处理请求。这个master-workers的工做模式和nginx是同样的。你还能够经过给master进程发送信号,让master进程建立更多worker进程,或者减小worker进程,还能够实现“平滑的重启”,即在不中断web请求服务的同时,从新启动进程,加载新的应用代码,这一点经过: rainbowsctl reload就能够实现。 多线程

此外若是你使用的是Ruby2.0,还能够在rainbows.rb里面打开 copy on write 特性,以下: 并发

preload_app true GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

可让多个进程共享加载应用程序框架和库的内存空间,节省不少物理内存。 app

总之对于大型多线程Ruby Web应用,推荐使用rainbows,我使用下来感受也很不错。

Puma

我在至关长一段时间都不怎么关注puma,由于puma是个单进程多线程服务器,没有cluster模式,不太适合真实有负载的环境,对于多核服务器,启动多进程跑cluster是必须的。可是最近Puma升级到2.0版本之后,也支持了多进程cluster模式,并且也是master-workers的方式,相似nginx和rainbows,请看配置文件:puma.rb

workers 0 # 指定建立多少个worker进程,若是0则不打开cluster模式 threads 0, 16 # 最少线程和最多线程,可根据请求量在这个范围自动伸缩

经过workers设置进程数,经过threads设置线程数,最大IO并发请求量等于进程数乘以最大线程数。Puma比较有意思的地方在于:

  1. 经过workers设置,能够在单进程和多进程cluster模式之间自动切换,若是是0,则不启动master进程,只有一个单进程,若是workers不是0,则启动1个master和多个workers。并且master进程不会加载应用代码,master进程占有内存很是少,固然这个的代价就是若是启动workers进程不少,启动时间会很长。
  2. 线程能够根据请求量自动在min和max之间伸缩,对于较少的请求,启动的线程数少,能够节省资源。

此外puma也支持“平滑的重启”,也提供了不少有趣的状态控制方式,请看puma.sh Puma启动的时候能够设置一个状态文件,它会把进程的运行状态写进去,方便你控制进程的运行。

Rainbows or Puma

我对Rainbows和Puma作了一些简单的性能压力测试,测试结果代表二者之间的性能差别很是小,Rainbows稍稍胜出。使用哪一个,更多取决于我的偏好。我以为大型应用使用Rainbows更好一些,但愿节省服务器资源的小型应用更适合用Puma。这是由于:

  1. Rainbows基于unicorn的代码,稳定性获得了大量高负载应用的考验。
  2. Rainbows提供了不少经过信号控制进程的手段,方便系统管理员干预应用服务器运行。
  3. 在单进程模式下Puma只有1个工做进程,单Rainbows仍然会启动master-worker模式,所以Puma的单进程更节省内存。
  4. Puma的线程能够根据请求自动伸缩,对于请求量小的应用,比较节省资源。

Zbatery

zbatery也是unicorn和rainbows的做者Eric Wong开发的,配置文件能够直接用rainbows的,它是rainbows的简化版本,只支持单进程多线程,没有master进程,信号支持的也不完整,并且好久没有升级过了。比较正规的生产环境可能就不太适合了。但zbatery的好处是特别节省内存,比单进程的puma还要节省不少内存,若是你想在一个VPS上跑不少web应用,每一个web应用流量都很小,那用zbatery到很是合适。

相关文章
相关标签/搜索