一,Apache vs Nginx
他們都是web服務器,都能伺服靜態文件,利用恰當的模塊也能伺服動態的web應用。Apache更加流行,擁有更多的功能;Nginx則相對小巧、快速、功能少。
Apache 和 Nginx都能在盒子外(out-of-the-box)伺服Ruby服務器,爲此你須要使用另外的插件來組合他們。
Apache 和 Nginx都能做爲反向代理,就是說他們可以把進來的 HTTP 請求發給其餘服務器,接着把該服務器的 HTTP 響應轉給客戶端,後面會看到爲何和這個有關係。
二,Mongrel以及其餘production環境的服務器 vs WEBrick
Mongrel是Ruby實現的應用服務器,具體來講:
1,在本身的進程空間中加載 Ruby 應用。
2, 建立一個 TCP socket,容許它能夠和外部世界通訊(例如Internet)。Mongrel 在這個socket上監聽 HTTP 請求,並把請求數據轉發給 Ruby 應用。
3,Ruby 應用返回一個描述 HTTP 響應的對象,Mongrel 將其轉換爲真正的 HTTP 響應字節,併發回到 socket 中。
然而 Mongrel 已經再也不維護了,其餘替代的服務器是:
- Phusion Passenger
- Unicorn
- Thin
- Puma
- Trinidad (JRuby only)
- TorqueBox (JRuby only)
接下來我會講一講他們和 Mongrel 的區別
WEBrick 和 Mongrel 很像,區別以下:
- WEBrick 不適合用於 production。WEBrick 徹底是用 Ruby 寫的;Mongrel( 以及其餘 Ruby 應用服務器)是部分 Ruby 部分C,主要是 Ruby,但它的 HTTP 解析器爲了性能是用 C 寫的。
- WEBrick 速度比較慢並且不夠強壯,有廣泛知道的內存泄漏問題,以及 HTTP 解析問題。
- 由於 WEBrick 是 Ruby 默認自帶的,因此 WEBrick 常常用於 development 環境下做爲默認服務器,而其餘的服務器則須要另外安裝。不建議在production 環境下使用 WEBrick 服務器,雖然由於某些緣由,Heroku 選擇了WEBrick 做爲默認服務器,他們之前使用的是 Thin,但我不知道他們爲何換到了 WEBrick。
三,應用服務器世界
當前全部的Ruby 應用服務器都是 HTTP 類型的,一些服務器直接將80端口暴露到 Internet 中,另外一些則沒有。
- 暴露80端口的:Phusion Passenger, Rainbows。
- 沒有直接暴露的:Mongrel, Unicorn, Thin, Puma。這些服務器必須必須置於反向代理服務器以後,好比Apache 和 Nginx。
- 我不瞭解 Trinidad 和 TorqueBox,因此就忽略了。
爲何有些服務器須要置於反向代理以後?
- 某些服務器的每一個進程在同一時間只能處理一個請求,若是想同時處理兩個請求,你就須要啓動多個服務器實例,都伺服同一個 Ruby 應用。這種應用服務器進程的集合稱爲應用服務器集羣(好比Mongrel Cluster, Thin Cluster)。而後你必須啓動 Apache 或者 Nginx,給集羣作反向代理,Apache/Nginx 會處理好集羣中不一樣應用實例間的請求分發。(更多內容參見章節 "I/O併發模型」)
- Web 服務器能夠緩存請求和響應。有些客戶端發送數據、接收數據的速度緩慢,你固然不但願應用服務器在等待客戶端收發數據時什麼也不幹,Web 服務器能夠隔離應用服務器和慢客戶端。Apache 和 Nginx 擅長同時不少事情,由於他們是多線程或者基於事件的。
- 大多數的應用服務器能夠伺服靜態文件,但不擅長,而Apache 和 Nginx能夠更快速度處理這件事情。
- 人們常常直接使用Apache 或者 Nginx伺服靜態文件,而不會處理須要轉發的請求(forward requests),這是比較安全的策略。Apache 和Nginx足夠聰明,能夠保護應用服務器遠離惡意請求。
爲何有些服務器能夠直接暴露在Internet中?
- Phusion Passenger 和其餘應用服務器不同,其中一個特色是能夠融入其餘服務器。
- Rainbows 的做者公開指出,Rainbows 能夠直接暴露在 Internet 中。他很是確認在解析 HTTP 過程當中不會輕易遭受攻擊。still, the author provides no warranty and says that usage is at own risk.
四,應用服務器對比
在這一章中,我會比較我提過的大多數服務器,但不包括 Phusion Passenger。Phusion Passenger 和其餘的不同,我會單獨開出一章。我還會忽略 Trinidad 和 TorqueBox,由於我對他們不是很瞭解,只有你用到 JRuby 的時候纔會涉及到他們。
- Mongrel 是塊暴露的石頭。像以前提到的,Mongrel 僅僅是單線程、多進程,因此它只用於集羣(cluster)中。沒有進程監控,意味着若是集羣中一個進程崩潰了,則須要手動重啓。人們須要使用額外的進程來照看 Mongrel,好比 Monit 和 God。
- Unicorn 是從 Mongrel 中fork出來的。支持監控必定數量的的進程:若是一個進程崩潰了,則會被主進程自動重啓。它能讓全部進程都監聽同一個共享的socket,而不是每一個進程使用單獨的socket,這會簡化反向代理的配置。像Mongrel同樣,Unicorn 是單線程、多進程。
- Thin 利用 EventMachine 庫,實現基於事件的 I/O 模型。它並非使用 Mongrel 的 HTTP 解析器,沒有基於 Mongrel。它的集羣節點沒有進程監控,因此你須要去監控進程是否崩潰。每一個進程監聽各自的socket,不像 Unicorn 同樣共享socket。理論上來講,Thin 的I/O 模型容許高併發,這也是 Thin 被應用的大部分場合。一個 Thin 的進程只能處理一個併發請求,因此你還須要集羣。關於這個古怪的性質,更多內容參見「I/O併發模型」。
- Puma 也是從 Mongrel 中fork出來的,但和 Unicorn 不同的是,Puma 被設計成多進程的。目前不支持集羣。你須要特別確認的是你能實現多核(You need to take special care to ensure that you can utilize multiple cores)。更多內容參見「I/O併發模型」。
- Rainbows 經過給不一樣的庫實現多種併發模型。
五,Phusion Passenger
Phusion Passenger 和其餘的不同。他直接融入 Apache 或者 Nginx,相似於 Apache 的 mod_php。就像 mod_php 使 Apache伺服 PHP 應用同樣, Phusion Passenger 也可使 Apache 或者 Nginx 伺服 Ruby 應用。Phusion Passenger 的目標是全部的事情作起來儘量地減小麻煩。
若是使用 Phusion Passenger的話,你不須要爲你的應用啓動一個進程或者集羣,爲
Apache/Nginx
配置靜態目錄,或者設置反向代理。
你只須要:
- 編輯web服務器的配置文件,寫入 Ruby 應用下public文件夾的路徑
- 沒有第二步。
全部的配置工做都在Web 服務器配置文件的指導下作完了,Phusion Passenger幾乎自動化了全部事情,不須要啓動集羣以及管理進程。啓動或者中止進程,他們崩潰時重啓,這些都被自動化了。和其餘應用服務器相比,Phusion Passenger 所須要作的改動工做很是少,這是人們使用 Phusion Passenger 的主要緣由。
和其餘應用服務器不一樣的是,Phusion Passenger 主要是用 C++ 寫的,速度很快。
Phusion Passenger 的企業版有更多的特性,好比自動回滾重啓,支持多線程,容錯部署。(such as automated rolling restarts, multithreading support, deployment error resistance, etc.)
基於以上緣由,
Phusion Passenger是當前最流行的 Ruby 應用服務器,服務於超過50,000 站點,包括大型站點:New York Times, Pixar, Airbnb。
六,Phusion Passenger vs 其餘服務器
相對其餘的服務器,Phusion Passenger 提供了更多的特性功能:
- 根據訪問量自動調整進程的數量。在資源有限的服務器上,咱們運行多個 Ruby 應用,而咱們的應用不對外公開,並且組織內的訪客天天的訪問量也很低,例如 Gitlab, Redmine等。Phusion Passenger 可以在進程不使用的時候掛起他們,須要的時候恢復進程,爲更重要的應用騰出資源。相比之下,其餘的服務器的全部進程會一直運行着。
- 有些服務器不適合某些特定的負荷。例如 Unicorn 爲輕量快速的請求而設計,See the Unicorn website section "Just Worse in Some Cases".
Unicorn 不擅長的負荷:
> 流(e.g. Rails 4 live streaming or Rails 4 template streaming)
> 調用 HTTP API
- 其餘的應用服務器須要用戶爲每一個應用至少啓動一個實例,相比之下,Phusion Passenger 支持一個實例多個應用。這大大減小管理員的開支。
- Phusion Passenger 支持多個 MRI Ruby, JRuby 和 Rubinius。Mongrel, Unicorn 和 Thin 只支持 MRI,Puma也支持三個。
- Phusion Passenger 不只支持 Ruby,它還支持 Python WSGI,因此一樣能運行 Django 和 Flask 應用。實際上,Phusion Passenger正在向多語言服務器發展的道路上前進,Node.js的支持已經列在計劃中。
- Out-of-band garbage collection。Phusion Passenger 能夠在請求的循壞外執行 Ruby 的垃圾回收,能夠潛在地減小几百毫秒的請求時間(reducing request times by hundreds of milliseconds)。Unicorn也有相似的功能,可是Phusion Passenger 的版本更加靈活,由於 1,it's not limited to GC and can be used for arbitrary work。2,Phusion Passenger的版本適應多進程應用,而 Unicorn 則不行。
- 自動回滾重啓(Automated rolling restarts)。Unicorn 以及其餘應用服務器的回滾重啓須要腳原本執行,Phusion Passenger 企業版自動幫你完成了。
七,I/O併發模型
- 單線程,多進程。Ruby 應用服務器中比較常見、流行的 I/O 模型,主要是由於 Ruby 生態系統中的多線程支持比較差。一個進程同時僅且只能處理一個請求,web 服務器經過多進程來進行均衡負載。這種模型比較穩定,開發者不會輕易形成併發bug。這種模型適合執行快速的短請求,不適合速度慢、長請求阻塞I/O的運算,例如 調用HTTP API。
- 純多線程。如今Ruby生態系統已經很支持多線程了,因此這種I/O模型變得切實可行。多線程支持高I/O併發,既適合短請求也適合長請求。開發者也很容易引入併發bug,幸運的是大多數框架按照這種方式設計,因此也不太可能發生。有一個須要注意的事情是,由於使用了全局解釋器鎖(GIL),MRI Ruby 解釋器不能均衡使用多個CPU內核,即便有多個線程。爲此,你可使用多個進程,每一個進程使用一個CPU內核。JRuby 和 Rubinius沒有GIL,因此他們的一個進程能夠均衡負載多個CPU內核 。
- 結合多線程、多進程。Phusion Passenger Enterprise 4之後版本實現了。你能夠輕易在如下模型切換:單進程多線程,純多線程,多進程多線程。這種模型給出了最好的選擇方式。
- 事件。這種模型和以前提到的模型不同。它容許極高的I/O併發,以及很是適合長請求。爲實現此功能,須要從應用到框架的詳細支持。然而主要的框架(Rails 和 Sinatra)並不支持事件模型。這也是實際上一個Thin進程同時不能處理多個請求的緣由,就像單線程多進程模型同樣。只有專門的框架才充分利用事件I/O模型,例如Cramp。
八,Capistrano
Capistrano和其餘的不同。在以前的全部章節中,「部署」指的是在服務器上啓動 Ruby 應用,而後對遊客開放,可是在這以前須要一些準備工做,例如:
- 將 Ruby 應用的代碼和文件上傳到服務器機器上。
- 安裝應用所依賴的庫。
- 建立或者遷移數據庫。
- 啓動或者中止應用依賴的守護進程,例如 Sidekiq/Resque 或者 whatever。
- 啓動應用時須要作的全部其餘事情。
在 Capistrano 的語義中,「部署」意味着去作全部的準備工做。Capistrano 不是一個服務器,反而是一個自動作那些準備工做的工具。你告訴 Capistrano 你的服務器在哪裏,以及每當你部署新版本應用的時候須要執行的命令,Capistrano 就能幫你上傳 Ruby 應用到服務器上而且運行你指定的命令。
Capistrano 老是與應用服務器組合使用,並不會替代應用服務器。反之亦然,應用服務器也不會替代 Capistrano。
固然 Capistrano 也不是必須使用的。若是你可使用 FTP 或者 手動上傳 Ruby 應用,每一次都執行相同的動做。其餘人厭倦這種重複,因此他們在 Capistrano 中自動執行這些步驟。