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到很是合適。

相關文章
相關標籤/搜索