使用的環境

系統與使用工具
Centos 7.6

重點整理

本篇介紹 PHP-FPM,不過要先從其他小傢伙開始介紹,先放上簡單的重點整理。

項目 介紹
FPM 接收特定 request 並且運行 PHP 腳本產生結果
CGI 介於 HTTP server 與 CGI program 溝通的工具、協定
FastCGI CGI 的改版,其 process 會持續運行,並支援分佈式運行
PHP-FPM 一種實作 FastCGI 的 process manager,原本是 PHP 的補丁,在 PHP 5.3.2 被官方加入 PHP

一、PHP-FPM 基本工作原理圖

二、FPM 介紹

fpm 是 FastCGI Process Manager 的縮寫。

其功能是專門接收特定 request 並且運行 php 腳本產生結果。

三、CGI 介紹

CGI 是一種協定,為了保證 web server 傳過來的資料是標準格式,簡單來說 CGI 是 web server 與 CGI 程式(如 php, python)間進行 “交談” 的一種工具或協定。

在 web server 接收到 request 時,會跟 request 內容進行對應處理,再返回對應的檔案給瀏覽器。

比如說:如果 request index.html,web server 會去找到這個檔案再丟給瀏覽器,但這僅限於靜態檔案,如果是像 index.php 這種動態檔案,web server 就會把這個 request 交給 php 解析器處理, php 解析器處理完後再將結果丟回給 web server,這過程 web server 會向 php 解析器傳送 post 或 url 或 http header 等等 CGI 有規定的資料和格式。

CGI program 針對每個 HTTP request 都會 fork 一個新的 process 來做事,例如:解析設定文件、初始化執行環境、處理 request 等,然後把這個 process 處理完的結果通過 web server 轉發給用戶,剛剛 fork 出的 process 也隨之退出,如果下次用戶再 request 動態資源,那麼 web server 又再次 fork process,如此周而復始,過程如下:

CGI program 的工作流程:

  1. 初始化各種相關變數
  2. 呼叫並初始化 zend 虛擬機
  3. 載入並解析 php.ini
    • 啟動 zend, zend 載入 php 腳本,做語法分析
    • 編譯 php 腳本成 opcode
    • 輸出結果
    • 關閉虛擬機
  4. 回傳結果給 web server

所以 CGI 的效能很差,因為在 CGI 協議下,每次的 request 都會尋找 php.ini 並進行環境的初始化,很浪費系統資源,每一次 request 都會有啟動和退出的過程(fork-and-execute 模式),所以之後才會誕生 FastCGI。

四、FastCGI 介紹

FastCGI 是一個協定,Fast + CGI,意思就是加速 CGI,提高傳統 CGI 處理 process 的效能。

在第一次啟動 php server 時,FastCGI 會先 fork 一個 master process 來解析設定文件 (/usr/local/php/etc/php-fpm.conf) 並初始化執行環境,然後再 fork 多個 worker process。

接下來,master process 會專注 listen port,當 request 過來時就將 request 分配給一個 worker process,然後立即可以接受下一個 request,再分配給下一個 worker process,提高了處理 request 的效率,而且當 worker process 不夠用時,master process 還可以根據設定預先啟動幾個 worker process 等著,若閒置的 worker process 太多時,也會關掉一些,這樣不僅提高了效能,也節省了系統資源。

FastCGI 採用 client-server 結構,可以將 web server 和 php 解析服務器分開,同時在腳本解析服務器上啟動一個或者多個腳本解析 process。當 web server 每次遇到動態行程時,可以將其直接交付給 FastCGI process 來執行,然後將得到的結果返回給瀏覽器。這種方式可以讓 web server 專注處理靜態 request ,或者將動態檔案的結果返回給 client 端,提高了整個應用系統的性能。

五、PHP-FPM 介紹

php-fpm 是對於 FastCGI 協議的具體實現,目的是 web server 跟 php 腳本的溝通。

php-fpm 可以啟動多個 child process 來運行 php 腳本,有效的使用多核心 cpu 的效能, 而每個 process 並不是 request 執行完就關閉,而是會先閒置,等待處理下一個 request,如果閒置太久,且已經太多 process 都閒置狀態才會關閉,所以不會有反覆啟動 processs 導致資源浪費。

php-fpm 負責管理一個 process pool 來處理來自 web server 的 HTTP 動態 request,在 php-fpm 中,master process 負責與 web server 進行通訊,接收 HTTP request,再將 request 轉發給 worker process 進行處理,worker process 主要負責動態 PHP 程式碼,處理完成後,將處理結果返回給 web 服務器,再由 web server 將結果發送給客戶端,這就是 php-fpm 的基本工作原理。

按照 FastCGI 的設計方式,在第一次啟動 php-fpm 之後,就會記住當時的 php server 設定,如果之後有進行修改,就要再重新啟動,才能再讀取到更新的設定。

此外,php-fpm 能做到平滑重啟,讓伺服器能穩定地提供服務。 處理的方式是讓新的 worker 套用新的設定,而舊的 worker 會繼續執行手上的工作,執行完畢就會被終止,再由新的worker接替,透過這樣的方式達到平滑重啟。

六、PHP-FPM 啟動、停止、重新啟動指令

# php-fpm 的設定檔
$ vim /usr/local/php/etc/php-fpm.conf

# 啟動 php-fpm
$ systemctl start php-fpm.service

# 停止 php-fpm
$ systemctl stop php-fpm.service

# 重新啟動 php-fpm
$ systemctl restart php-fpm.service

參考資料