CGI、FastCGI 與 PHP-FPM:從 Web 伺服器效能瓶頸說起
在現代 Web 開發中,高效能的伺服器架構是網站穩定運行的基石。然而,許多剛接觸後端開發的工程師,對於 Nginx、FastCGI 和 PHP-FPM 這幾個關鍵詞的關係感到困惑。要真正理解它們,我們需要從 Web 伺服器與動態應用程式溝通的最原始方式——CGI 談起。
1. CGI:開創動態網頁的元老,但效率低落
CGI (Common Gateway Interface) 是 Web 伺服器與外部應用程式(如 PHP、Perl 腳本)互動的最初標準。它的工作模式簡單而粗暴:
使用者發送一個動態請求。
Web 伺服器(如 Apache)接收請求後,為此請求啟動一個全新的進程。
這個新進程負責執行腳本,處理業務邏輯,並產生 HTML 內容。
進程執行完畢後,立即終止。
這種「一請求一進程」的模式,在流量低時還能應付,但當網站流量一高,Web 伺服器會不斷地重複「建立進程 -> 執行腳本 -> 銷毀進程」的動作。進程的啟動與銷毀本身就是一筆不小的系統開銷,這會迅速耗盡伺服器的 CPU 和記憶體資源,導致效能瓶頸。簡單來說,CGI 就像是每次接待一位客人,都要重新蓋一棟房子,用完就拆掉。這種方式顯然是無法規模化的。
2. FastCGI:持久化的進程,效能大幅提升
為了解決 CGI 的效能問題,FastCGI (Fast Common Gateway Interface) 應運而生。它是一種協議,核心思想是用持久化的進程來處理請求。
FastCGI 的工作模式完全不同:
Web 伺服器在啟動時,不會直接處理動態請求,而是將這些請求轉發給一個或多個已經在後台持續運行的 FastCGI 進程。
這些 FastCGI 進程會形成一個「進程池」,隨時準備接收請求。
Web 伺服器與這些 FastCGI 進程之間會建立一個長久存在的通訊介面(通常是 TCP/IP Socket 或 Unix Domain Socket)。
當請求到達時,Web 伺服器透過這個介面將請求內容傳送給一個空閒的 FastCGI 進程。
進程處理完請求後,將結果回傳,然後繼續等待下一個請求,而不是結束。
這種方式避免了頻繁地創建和銷毀進程的開銷,極大地提升了伺服器處理動態請求的效能。FastCGI 就像是建了一座餐館,服務生(FastCGI 進程)隨時待命,客人一來就能馬上點餐,服務結束後服務生繼續等待下一位客人,無需重複建拆餐館。
3. Nginx、PHP-FPM 與 FastCGI 協議的完美協作
在現代的 Web 伺服器架構中,Nginx 搭配 PHP-FPM 是主流選擇。它們之間的關係可以這樣總結:
Nginx:高效能的 Web 伺服器。它的角色是門面和反向代理,負責接收所有來自外部的 HTTP 請求。它擅長處理靜態檔案(如圖片、CSS、JS)和高效能的併發連接。
PHP-FPM (PHP FastCGI Process Manager):PHP 的 FastCGI 進程管理器。它是一個實現了 FastCGI 協議的軟體,專門用來管理多個 PHP 解析器進程,形成一個進程池。
FastCGI:Nginx 與 PHP-FPM 之間唯一的通訊語言。
它們的協作流程如下:
使用者請求
http://example.com/index.php
。Nginx 接收到請求,判斷出這是一個 PHP 腳本。
Nginx 知道自己無法執行 PHP,於是它根據設定檔(例如
fastcgi_pass 127.0.0.1:9000;
),透過 FastCGI 協議,將這個請求轉發給運行在9000
埠的 PHP-FPM。PHP-FPM 從它的進程池中找到一個空閒的 PHP 工作進程,並將請求交給它。
這個 PHP 進程執行
index.php
腳本,處理完後將結果(HTML、JSON 等)回傳給 PHP-FPM。PHP-FPM 再將結果透過 FastCGI 協議回傳給 Nginx。
最後,Nginx 將這個結果組合成一個完整的 HTTP 回應,發送給使用者的瀏覽器。
這個分工模型非常清晰且高效:Nginx 專注於處理網路 I/O 和靜態內容,PHP-FPM 專注於高效地處理 PHP 程式碼。兩者透過 FastCGI 協議無縫銜接,共同提供高效能的動態網頁服務。這也是為什麼 Nginx + PHP-FPM 成為當今主流 Web 伺服器架構的原因。
沒有留言:
張貼留言