---
# System prepended metadata

title: 2021 年 03 月

---

2021 年 03 月
===

## 蒼時

> Ruby 世界裡面有很多 Application 伺服器，差異在哪裡？為什麼 Passenger 需要依靠 Nginx 呢？

## Application Server

> 這個名詞最初是用來討論主從式架構系統時，用來區分資料庫伺服器、檔案伺服器等的不同。但現今常指能執行Web應用程式的Web伺服器
> - [維基百科](https://zh.wikipedia.org/wiki/%E6%87%89%E7%94%A8%E7%A8%8B%E5%BC%8F%E4%BC%BA%E6%9C%8D%E5%99%A8)

從這個角度來看，Ruby 常見的 Puma、Passenger、Unicorn 都屬於 Application Server 的範圍

## Web Server

簡單來說可以提供 Web 服務的都屬於 Web Server 的範圍，也因此 Nginx、Puma、Passenger、Unicorn 也都屬於 Web Server 的範圍

## (Reverse) Proxy Server

> 也稱網路代理，是一種特殊的網路服務，允許一個（一般為客戶端）通過這個服務與另一個網路終端（一般為伺服器）進行非直接的連接。一些閘道器、路由器等網路裝置具備網路代理功能。一般認為代理服務有利於保障網路終端的隱私或安全，防止攻擊。
> - [維基百科](https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8)

我們在 Rails 正式環境的部署上，通常會用 Nginx 搭配 Puma、Passenger 等 Web Server 實際上是為了將「擅長」的事情分工處理。

在 Ruby（以及其他某些語言）處理靜態檔案的效率是很差的，舉例來說 Nginx 可能只需要在硬碟讀取檔案後回傳給使用者，但經過 Puma 處理時卻需要先呼叫 Ruby 來處理，並且轉接到 Rails 手上經過好幾個標準程序，才會去讀取檔案再進行回傳，而這中間就會造成很大的時間差。

也因此我們會將同時具有 Web Server 和 Proxy Server 機制的 Nginx 作為前面的處理方案，當連線請求出現後先由 Nginx 判斷是否為靜態檔案來決定要以 Web Server 的方式處理，還是 Proxy 給後面的 Application Server 做動態網站相關的處理。

## Puma / Passenger / Unicorn 比較

* Puma 是 Multi-threading 為基礎設計的
* Unicorn 和 Passenger 預設都是 Process 為基礎設計的

基本上要考慮到時代背景，Unicorn 和 Passenger 都是在 Thread 還沒有到非常成熟被應用在 Web 上的時代所開發的（要考慮到當時硬體、演算法的發展）而 Puma 則是比較晚才推出，因此是以 Thread 為前提設計。

不過 Passenger 在企業版裡面有提供 Multi-threading 的支援，而 Puma 也可以利用增加 Worker 來產生多個 Process 去提供服務。

> Ruby 受限於 GVL 的限制，因此無法順利的讓 Thread 在不同的 CPU 上切換來提高效率，因此增加 Process 數量在某些情境上確實可以更加善用 CPU。

Puma 和 Unicorn 都是獨立的 Ruby Gem 來運行，而 Passenger 除了提供 Standalone 模式可以用 Gem 安裝（實際上會包 Nginx 在裡面），更常見的是作為 Nginx 的 Module 來使用。

> Passenger 在這個情境來看，他本身只提供了 Application Server 的部分但 Web Server 是靠 Nginx 提供的。

## Rack

Puma / Passenger / Unicorn 之所以可以作為 Ruby 的 Application Server 提供服務，是因為 Ruby 有一個官方的標準介面叫做 Rack 定義了標準，因此只要能產生正確的 Rack 呼叫就能夠被任意的 Ruby 專案所使用。

> 這幾個 Application Server 底層的呼叫牽涉到一些 C 語言的實作，這邊就不特別描述。