nginx + php-fpm 是現在常常用來與代替以前的 php apache 伺服器,其最大的優點是使用的系統資源較少,並且 nginx 對於靜態檔案的處理速度非常快,本篇將講解 nginx 與 php-fpm 之間是如何運作的。
nginx 是什麼 ?
首先來了解一下 nginx 是什麼,nginx 是一個 web server,其主要功能是反向代理、負載平衡器和 HTTP 快取,nginx 本身就能夠做一個靜態檔案伺服器,現在最常主要負責:
- 處理靜態檔案
- 依據規則轉發 request
- 資料壓縮 (gzip)
- 傳輸的資料加密 (https)
其沒有一定要用於 php,可以依據情況將 request 丟給其他程式語言處理,或是將 request 丟給不同的 php 版本處理。
php-fpm 是什麼 ?
fpm 是 FastCGI Process Manager 的縮寫,其功能非常的單純,專門接收特定 request 並且運行 php 腳本產生結果。
fpm-fpm 可以啟動多個 child process 來運行 php 腳本,有效的使用多核心 cpu 的效能
而每個 process 並不是 request 執行完就關閉,而是會先閒置,等待處理下一個 request,如果閒置太久,且已經太多 process 都閒置狀態才會關閉,所以不會有反覆啟動 processs 導致資源浪費。
例如下面得設定
pm.start_servers = 4 pm.max_children = 10 pm.min_spare_servers = 2 pm.max_spare_servers = 6 pm.max_requests = 500
其效果為:
- 伺服器啟動時就開啟 4 個 process
- 最多 10 個 children process
- 最小閒置 process 數量
- 最大閒置 process 數量
- 一個 process 處理 500 個 request 後會重啟
nginx 與 php-fpm 運作說明
這邊以常見的 php-fpm 設定來說明
server { gzip on; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.2-fpm.sock; } }
這設定有幾項規則:
- 啟用壓縮 (gzip)
- url path 是以
.php
結尾的丟給 php-fpm 處理 - 其他 request 檢查該路徑是否是檔案或資料夾,如果是傳回檔案,否則回應 404 not found
而靜態檔案與 PHP 的 request 實際運作經過是不同的,下面圖片解說
檔案 request 的運作
- 客戶端發送 request
- nginx 尋找到對應的檔案並讀取
- 返回檔案的資料給使用者
PHP request (.php 結尾的 request) 的運作
- 客戶端發送 request
- 將 request 丟給 php-fpm 來處理
- php-fpm 找到對應的 php 腳本檔案並且執行
- 講腳本執行的結果丟回給 nginx
- nginx 將結果返回給使用者
常見問題
網頁出現 504 Gateway timeout 原因與解決方法?
以上面這張圖解說,nginx 轉發 request 給 php-fpm 後會開始等 output,而 nginx 會設定一個等待回應 timeout 的設定值,假如 php-fpm 超過這個時間都沒有回應 (php執行太久) 那就會顯示 504 Gateway timeout
※ 預設 php-fpm 是沒有設定執行時間上限
解決方法有兩種:
- 調高 nginx 的等待時間
調整 nginx.conf 設定 fastcgi_read_timeout:
location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.2-fpm.sock; fastcgi_read_timeout 300; }
- 降低 php-fpm 的可執行時間上限
調整 php-fpm 的 php.ini 設定 max_execution_time:
max_execution_time = 30