[講解] nginx 與 php-fpm 運作介紹與設定

      在〈[講解] nginx 與 php-fpm 運作介紹與設定〉中尚無留言

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 的運作

  1. 客戶端發送 request
  2. nginx 尋找到對應的檔案並讀取
  3. 返回檔案的資料給使用者

PHP request (.php 結尾的 request) 的運作

  1. 客戶端發送 request
  2. 將 request 丟給 php-fpm 來處理
  3. php-fpm 找到對應的 php 腳本檔案並且執行
  4. 講腳本執行的結果丟回給 nginx
  5. nginx 將結果返回給使用者

常見問題

網頁出現 504 Gateway timeout 原因與解決方法?

以上面這張圖解說,nginx 轉發 request 給 php-fpm 後會開始等 output,而 nginx 會設定一個等待回應 timeout 的設定值,假如 php-fpm 超過這個時間都沒有回應 (php執行太久) 那就會顯示 504 Gateway timeout

※ 預設 php-fpm 是沒有設定執行時間上限

解決方法有兩種:

  1. 調高 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;
    }
  1. 降低 php-fpm 的可執行時間上限

調整 php-fpm 的 php.ini 設定 max_execution_time:

max_execution_time = 30