這裡介紹一些 Nginx 與 PHP-FPM 相關的設定檔調整方法與技巧,最佳化網頁伺服器的效能。
最近我把網站伺服器從原本的 Ubuntu Linux 14.04 換成新的 CentOS Linux 7(LEMP 架構),PHP 版本也升級成 PHP 7,結果更換之後,網頁看似正常,但不定時會出現 MariaDB 記憶體不足的錯誤訊息:
180505 11:48:00 [ERROR] Plugin 'InnoDB' init function returned error. 180505 11:48:00 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. 180505 11:48:00 [ERROR] mysqld: Out of memory (Needed 128917504 bytes) 180505 11:48:00 [ERROR] mysqld: Out of memory (Needed 96681984 bytes)
起初以為是 MariaDB 的設定問題,但是後來才發現是因為系統記憶體不足,導致 MariaDB 沒有足夠的記憶體可以使用。
PHP-FPM 中有一個 process manager 功能,它負責管理 PHP-FPM 的工作行程,可以在網路流量較大時,增加 PHP-FPM 行程數量,而沒有流量時則減低 PHP-FPM 的行程數量,在安裝好 PHP-FPM 之後,建議仔細調整一下 process manager 相關的設定,這樣可以讓伺服器的效能更好一點,而且也可以避免開太多 PHP-FPM 行程,把系統記憶體耗盡。
PHP-FPM 的 process manager 設定可在 pool 設定檔中調整,在 CentOS Linux 中,PHP 5 的 PHP-FPM 設定檔案放在 /etc/php5/fpm/pool.d/www.conf
,而 PHP 7 的 PHP-FPM 設定檔則是放在 /etc/opt/rh/rh-php71/php-fpm.d/www.conf
。設定檔的實際位置也會跟安裝的方式有關,如果您系統上的 PHP-FPM 的設定檔位置不同,就自己尋找一下類似的路徑。
在調整 PHP-FPM 的行程管理規則時,建議可以開啟 PHP-FPM 服務的狀態監控網頁,方便觀察調整後的效果。
process manager 有一系列的選項可以調整,首先找到 pm
(process manager)參數:
pm = dynamic
pm
可用的值如下:
static
:固定行程數量(數量為 pm.max_children
)。dynamic
:動態行程數量(根據 pm.max_children
、pm.start_servers
、pm.min_spare_servers
、pm.max_spare_servers
動態調整)。ondemand
:動態行程數量(根據 pm.max_children
、pm.process_idle_timeout
動態調整)。static
就是單純維持固定的 PHP-FPM 行程數量,若記憶體很充足的伺服器,可以考慮使用這種設定,效能會很好,不過缺點就是沒有流量時還是會佔用很多記憶體。
dynamic
與 ondemand
都會根據網路流量來動態調整 PHP-FPM 的行程數量。ondemand
就是很單純看需要多少行程就建立多少,沒用的就關閉,最節省記憶體,但是由於開關行程頻繁,所以效能較差。dynamic
可以設定一些規則,讓流量大的時候開啟多一點工作行程,而在沒有流量時,也會保留一些行程等待隨時接收新的連線,效能與耗費的記憶體都介於 static
與 ondemand
之間,算是折衷的方案。
pm.max_children
這個參數在 static
模式下就是代表開啟的行程數,而在 dynamic
與 ondemand
模式下,則是代表最大可開啟的行程數量:
pm.max_children = 50
這個值是最重要的,設太小的話會造成伺服器處理連線的速度下降,設太大的話會耗盡系統記憶體(造成當機),所以要依照自己系統上的資源來調配。
建議可以先用 top
指令,看看單一 PHP-FPM 行程大約佔用多少記憶體,然後再估算一下整個系統可以容納多少 PHP-FPM 的行程。
pm.start_servers
可設定 PHP-FPM 服務在一開始啟動時,要配置多少個行程:
pm.start_servers = 5
pm.min_spare_servers
可設定 PHP-FPM 最小閒置行程的數量:
pm.min_spare_servers = 5
pm.max_spare_servers
可設定 PHP-FPM 最大閒置行程的數量:
pm.max_spare_servers = 35
pm.max_requests
可設定單一 PHP-FPM 最多可以處理多少個連線,當一個工作行程處理的連線數達到這個值的時候,就會強制關閉此行程,重新產生另一個新的行程:
pm.max_requests = 500
修改好 PHP-FPM 設定檔之後,重新啟動 PHP-FPM 服務,讓新設定生效:
# PHP 5 sudo systemctl restart php-fpm # PHP 7 sudo systemctl restart rh-php71-php-fpm
檢查 PHP-FPM 是否正常啟動:
# PHP 5 sudo systemctl status php-fpm # PHP 7 sudo systemctl status rh-php71-php-fpm
以下是一些 Nginx 伺服器常用的設定配置技巧。
在 CentOS Linux 中安裝好 Nginx 之後,主要的設定檔都放在 /etc/nginx/nginx.conf
,建議可以仿照 Debian/Ubuntu 的管理方式,建立兩個放置個別網站設定的目錄:
/etc/nginx/sites-available/ /etc/nginx/sites-enabled/
所有網站的設定檔都放在 /etc/nginx/sites-available/
之中,對於要啟用的網站則在 /etc/nginx/sites-enabled/
建立連結檔。
接著在 /etc/nginx/nginx.conf
中的 http
區塊尾端加上一個 include
設定:
http { # [略] include /etc/nginx/sites-enabled/*; }
這樣就可以方便管理多個網站的設定了。
Nginx 的 worker_processes
可以設定 worker 行程的數量,通常如果 CPU 沒有其他用途的話,可以把這個值設定成 CPU 的核心數:
# 4 核心的 CPU
worker_processes 4;
或是直接設定為 auto
,讓 Nginx 自動偵測可用的 CPU 核心數:
# 自動偵測 CPU 核心數
worker_processes auto;
另外 worker_connections
可設定每個 worker 可同時處理的連線數上限值:
events { # 同時可處理 1024 條連線 worker_connections 1024; }
也就是說整台 Nginx 伺服器可以同時處理的連線數上限值即為 worker_processes * worker_connections
。
顯示 Nginx 的詳細版本可能會暴露出伺服器可能的弱點,建議可以將其隱藏起來:
http { # 不顯示 Nginx 版本 server_tokens off; }
通常隱藏檔都是跟系統有關的檔案,不會是一般的網頁,所以禁止網頁伺服器顯示隱藏檔可以增加系統安全性:
server { # [略] location ~ /\. { access_log off; log_not_found off; deny all; } }
open_file_cache
是 Nginx 的檔案資訊快取功能,適用於有大量靜態檔案的網站,它會將常用的檔案資訊放入快取(並非將檔案內容放入快取),加速靜態檔案的處理速度。
http { # [略] # 檔案資訊快取 open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; }
在 events
的設定中,可以加入以下設定,可讓效能更好:
events { # [略] # 使用 epoll 效能較好 use epoll; # 可同時接受多條連線 multi_accept on; }
參考資料:If Not True Then False、haydenjames、Servers for Hackers、Servers for Hackers