2017年12月5日 星期二

打造企業高承載需求的 Nginx(PHP-FPM篇)


在基礎建設篇我們建立了可以處理靜態網頁的nginx網頁服務,但實際的應用裡我們通常也需要處理動態網頁以提供用戶更好的互動體驗,本篇將以最常見的LNMP架構、說明php套件的安裝與相關設定。

有別於apache以掛載本地module的方式來解析php,Nginx是以location方式、將副檔名為php的檔案傳給fastcgi處理,也就是接下來我們要安裝的php-fpm。


Step 1 安裝remi套件庫
[root@centos7 ~]# rpm -ivh https://rpms.remirepo.net/enterprise/remi-release-7.rpm


Step 2 透過remi源安裝php5.6 、啟動php-fpm並設定開機啟用
[root@centos7 ~]# yum install php php-fpm php-cli php-common php-xml php-gd php-mysql php-mcrypt php-mbstring php-soap php-pdo php-xmlrpc php-pecl-jsonc php-pecl-zip --enablerepo=remi-php56
[root@centos7 ~]# systemctl start php-fpm
[root@centos7 ~]# systemctl enable php-fpm


Step 3 確認你的php.ini設定檔以下參數是否需調整
[root@centos7 ~]#  nano /etc/php.ini

date.timezone = Asia/Taipei
display_errors = off
file_uploads = On
upload_max_filesize = 50M
post_max_size = 500M
max_file_uploads = 20
memory_limit = 512M

  • date.timezone時區
  • display_errors網頁上是否顯示錯誤訊息,一般用於debug而不會在生產環境中啟用
  • file_uploads是否允許透過php上傳檔案
  • upload_max_filesize上傳單一檔案的最大容量限制,對應nginx的client_max_body_size參數
  • post_max_size使用post傳資料的最大容量限制
  • max_file_uploads單次最多可上傳的檔案數量,隱藏參數、預設為20
  • memory_limit 執行每個scripts時使用memory的大小限制


Step 4 確認你的php-fpm.conf設定檔以下參數是否需調整
[root@centos7 ~]# nano /etc/php-fpm.conf

include=/etc/php-fpm.d/*.conf
pid = /var/run/php-fpm/php-fpm.pid

;log_level = notice

  • include=/etc/php-fpm.d/*.conf 主要的設定參數其實都存放在這個目錄下
  • pid Process id的存放位置
  • log_level 日誌紀錄的程度,預設notice等級就會開始記錄

[root@centos7 ~]# nano /etc/php-fpm.d/www.conf

user = nginx
group = nginx
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
listen.backlog = 8192
pm = static
pm.max_children = 4096
pm.start_server = 2048
pm.min_spare_servers = 1024
pm.max_spare_servers = 4096

  • user 預設是www(配合預設的apache web service),此處更改為nginx
  • group 預設是www(配合預設的apache web service),此處更改為nginx
  • listen 預設只監聽Local端 tcp 9000,也可設定本機IP讓php-fpm主機服務於區網之中
  • listen.allowed_clients 承上若php-fpm主機服務於區網之中,須加入要服務的web主機IP
  • listen.backlog socket隊列大小,建議與nginx的backlog設置一致即可
  • pm 程序管理可設置為static,優點是直接fork出pm.max_children的程序數量
  • pm程序管理可設置為dynamic,fork出的程序則會動態調整,較節省資源
  • pm.start_server 初始就啟用的程序數量,pm為dynamic時才有作用
  • pm.min_spare_servers 最小占用的程序數量,pm為dynamic時才有作用
  • pm.max_spare_servers 最大占用的程序數量,pm為dynamic時才有作用

由於fastcgi特性,會事先準備好程序供web server呼叫,以節省時間,若採取static的方式管理,會直接開啟pm.max_children的最大值,雖然當下沒有那麼多的用戶存取,但資源會一直佔用,以每一個php-cgi約莫占用20M的記憶體來說,pm.max_children設置為1000就會占用20GB的記憶體,這樣的設置比較適合瞬間會湧入大量需求的應用。

Step 5 修改相關權限給nginx用戶並平滑重載php-fpm
[root@centos7 ~]# chown -R nginx:nginx /var/log/php-fpm
[root@centos7 ~]# chown -R nginx:nginx /var/lib/php
[root@centos7 ~]# systemctl reload php-fpm

在生產環境中,通常建議用reload取代restart,這兩者的差異在於,restart的動作是先stop service後再start service,而reload是讓service重新載入設定參數。

Step 6 調整nginx設定檔以辨識副檔名為php的處理辦法
[root@centos7 ~]# nano /etc/nginx/conf.d/www.tomyhome.com.conf

# 找到網站實體根目錄定義這段、新增index.php字段並於其後加上另一段location描述

root /var/www/html;
index index.php index.htm index.html;

location ~ .*\php$ {
   root /var/www/html;
   fastcgi_pass  127.0.0.1:9000;
   fastcgi_index index.php;
   expires off;
   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
   include           fastcgi_params;
}

平滑重載nginx
[root@centos7 ~]# systemctl reload nginx





是否讓PHP-FPM監聽unix socket?
PHP-FPM在listen的時候提供了兩種方式,一種是TCP,一種是unix socket,邏輯上透過socket file可以直接聯繫,速度會快過較嚴謹的TCP/IP層層通關,如果php-fpm和web service是在同一台主機上的話,就可以採取socket file的方式溝通,此處的調整會涉及到www.conf與nginx設定檔的部分修改。

編輯 /etc/php-fpm.d/www.conf,找到以下並將其註解
listen = 127.0.0.1:9000
於該行後新增(路徑/dev/shm是tmpfs,速度要比有些教程所使用的/tmp 磁碟路徑快得多。)
listen.mode = 0666
listen = /dev/shm/php-fpm.sock
建立socket file並重啟php-fpm服務
[root@centos7 ~]# touch /dev/shm/php-fpm.sock
[root@centos7 ~]# chown nginx:nginx /dev/shm/php-fpm.sock
[root@centos7 ~]# chmod 666 /dev/shm/php-fpm.sock
[root@centos7 ~]# systemctl restart php-fpm
編輯 /etc/nginx/conf.d/www.tomyhome.com.conf,找到以下並將其註解
fastcgi_pass    127.0.0.1:9000;
於該行後新增
fastcgi_pass    unix:/dev/shm/php-fpm.sock;
重啟nginx服務
[root@centos7 ~]# systemctl restart nginx




本文內容參閱以下連結:
小漳子的工作筆記
Phper進階
Puritys blog

php中fastcgi和php-fpm是什麼東西
[教學] 在 CentOS 中安裝 PHP-FPM for Nginx
使用socket方式連接Nginx優化php-fpm性能
nginx和php-fpm 是使用 tcp socket還是 unix socket?

0 意見: