php-fpm配置解說(PHP-FPM參數優調)
[重要通告]如您遇疑難雜癥,本站支持知識付費業務,掃右邊二維碼加博主微信,可節省您寶貴時間哦!
最近處理一些PHP腳本的時候,要經常用到php-fpm,這個東西真是費腦殼,但也沒有啥好的辦法,該用還得用,不然也沒有其他啥好的辦法來替代品!
php-fpm解說
php-fpm全名是PHP FastCGI進程管理器
php-fpm啟動后會先讀php.ini,然后再讀相應的conf配置文件,conf配置可以覆蓋php.ini的配置。
啟動php-fpm之后,會創建一個master進程,監聽9000端口(可配置),master進程又會根據fpm.conf/www.conf去創建若干子進程,子進程用于處理實際的業務。
當有客戶端(比如nginx)來連接9000端口時,空閑子進程會自己去accept,如果子進程全部處于忙碌狀態,新進的待accept的連接會被master放進隊列里,等待fpm子進程空閑;
這個存放待accept的半連接的隊列有多長,由 listen.backlog 配置。
php-fpm配置與參數優調
配置文件位置一般在PHP目錄下的etc/php-fpm.d/*.conf
pm.max_children = 100
最大子進程數量,越多越好,一般每個php-cgi所耗費的內存為20M左右
如果最大數量設置為100,則在峰值的時候php-cgi所耗內存在2000M以內
如果這個值設置的比較小,那么等待的請求時間會出現502超時
4G內存服務器可以設置成200
pm.start_servers = 20
pm.start_servers:啟動時創建的子進程數,10~20之間就可以,20個的話是400M內存
pm.max_requests = 10240
為避免內存泄露,php-fpm有這么一個機制,當一個php-cgi進程處理的請求數達到這個配置后,則會自動重啟該進程
所以在高并發中,經常導致502錯誤
解決方法就是把這個值設置大一些,減少進程重啟次數,減少高并發情況下502錯誤。
request_terminate_timeout = 400
單個請求的超時中止時間,超時后會終止進程,nginx發現信號斷了,就會給客戶端返回502錯誤。
和php.ini的max_execution_time配置不沖突,誰先達到時間誰先起作用。
由于程序中有請求第三方接口等待,所以建議這個值設置為400秒,長一點不會出現502錯誤
pm.min_spare_servers = 10
保證空閑進程數最小值,如果空閑進程小于此值,則創建新的子進程
pm.max_spare_servers = 30
保證空閑進程數最大值,如果空閑進程大于此值,此進行清理
rlimit_files = xxx
設置文件打開描述符的rlimit限制,可使用 ulimit -n 查看
其他:pm.status_path = /status
可以用來查看php-fpm運行情況,配置打開后再在nginx進行代理轉發,就可以在瀏覽器訪問了
/status顯示的參數意義:
pool – fpm池子名稱,大多數為www
process manager – 進程管理方式,值:static, dynamic or ondemand. dynamic
start time – 啟動日期,如果reload了php-fpm,時間會更新
start since – 運行時長
accepted conn – 當前池子接受的請求數
listen queue – 請求等待隊列,如果這個值不為0,那么要增加FPM的進程數量
max listen queue – 請求等待隊列最高的數量
listen queue len – socket等待隊列長度
idle processes – 空閑進程數量
active processes – 活躍進程數量
total processes – 總進程數量
max active processes – 最大的活躍進程數量(FPM啟動開始算)
max children reached - 進程最大數量限制的次數,如果這個數量不為0,那說明你的最大進程數量太小了,請改大一點。
slow requests – 啟用了php-fpm slow-log,緩慢請求的數量
還可以在訪問時,在網址后面追加?full,可以查看更詳細的狀態,參數值有:
pid – 進程PID,可以單獨kill這個進程.
state – 當前進程的狀態 (Idle, Running, …)
start time – 進程啟動的日期
start since – 當前進程運行時長
requests – 當前進程處理了多少個請求
request duration – 請求時長(微妙)
request method – 請求方法 (GET, POST, …)
request URI – 請求URI
content length – 請求內容長度 (僅用于 POST)
user – 用戶 (PHP_AUTH_USER) (or ‘-’ 如果沒設置)
script – PHP腳本 (or ‘-’ if not set)
last request cpu – 最后一個請求CPU使用率。
last request memorythe - 上一個請求使用的內存
nginx轉發配置:
location /status { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; }
其他:ping.path = /ping
用于外部檢測FPM是否存活并且可以響應請求
nginx轉發配置:
location /ping { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; }
注:macOS系統對進程數、打開文件數等等有限制,為了方便操作,直接在Linux下測試。
修改配置后重載配置文件:
ps aux|grep php-fpm 得到Ss類型運行的pid
kill -USR2 pid
php7以上版本的php-fpm參數配置
php-fpm的核心參數配置,默認如下:
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
只針對動態方式dynamic說明如下:
max_children:動態方式下限定php-fpm的最大進程數
start_servers:動態方式下的起始php-fpm進程數量
min_spare_servers :動態方式空閑狀態下的最小php-fpm進程數量
max_spare_servers :動態方式空閑狀態下的最大php-fpm進程數量
這些參數如果注意改錯了參數會導致php-fpm啟動不了,nginx也就無法訪問php文件,可查看日志排查錯誤:
/usr/local/php/var/log/php-fpm.log
規則匯總:
1.max_children 必須大于 min_spare_servers
2.max_children 必須大于 max_spare_servers
3.start_servers 必須大于 min_spare_servers
4.start_servers = min_spare_servers + (max_spare_servers - min_spare_servers) /
php-fpm全局配置說明(PHP5.6載入)
配置里面的所有相對路徑,都是相對于php的安裝路徑。
除了有php-fpm.conf配置文件外,通常還有其他的*.conf配置文件(也可以不要,直接在php-fpm.conf配置)用于配置進程池,不同的進程池可以用不同的用戶執行,監聽不同的端口,處理不同的任務;多個進程池共用一個全局配置。
[www] #進程池的名字; user = www group = www #以什么用戶什么組的權限來運行[www]這個進程池,用戶,必須要設置,用戶組,如果沒有設置,則默認用戶的組被使用; listen.backlog = 65535 #子進程未accept處理的客戶端請求隊列大小,-1 on FreeBSD and OpenBSD,其他平臺默認65535,高并發時重要,合理設置會及時處理排隊的請求;太大會積壓太多,處理完后nginx在前面都等超時斷開這個和fpm的socket連接了,就杯具了。不要用-1,建議1024以上,最好是2的冪值(注意:不同版本的默認值是不同的,php5多是128,php7多是511)。 #1:一個池共用一個backlog隊列,所有的池進程都去這個隊列里accept連接; #2:最大數量受限于系統配置cat /proc/sys/net/core/somaxconn,系統配置修改:vim /etc/sysctl.conf,增加net.core.somaxconn =1024則最大為1024,然后php最大的backlog可以到1024。 listen = 127.0.0.1:9000 #進程池[www]的監聽端口,可用格式為:'ip:port','port','/path/to/unix/socket'。每個進程池都需要設置。如果nginx和php在不同的機器上,只能用機器真實ip+端口的格式,如果在同一臺機器上,還可以選擇unix soxket方式,這種理論上速度會提升31%,但高并發下不夠穩定。 listen.owner = www listen.group = www listen.mode = 0666 #unix socket設置選項,如果使用tcp方式訪問,這里注釋即可。 listen.acl_users = www,php #當系統支持 POSIX ACL(Access Control Lists)時,可以設置使用此選項。 當設置了的時候,將會忽略 listen.owner 和 listen.group。值是逗號分割的用戶名列表。 PHP 5.6.5 起可用。 listen.acl_groups=web #參見 listen.acl_users。 值是逗號分割的用戶組名稱列表。 PHP 5.6.5 起可用。 listen.allowed_clients = 127.0.0.1 #允許訪問FastCGI進程的IP白名單,設置any為不限制IP,如果要設置其他主機的nginx也能訪問這臺FPM進程,listen處要設置成本地可被訪問的IP。每個地址是用逗號分隔。如果沒有設置或者為空,則允許任何服務器請求連接。 process.priority = -19 #該池進程的權限,同樣要master進程是root用戶才有效,和全局那個一樣,不設置的話會繼承master進程的優先級。 pm = dynamic #可選static,dynamic,ondemand,也就是說php-fpm有三種進程管理模式,默認dynamic。 #1:static,固定啟動若干(即pm.max_children)php進程,保持不變。 #有效配置:pm.max_children #2:ondemand,這種模式剛啟動時不會啟動任何php進程,只有php-fpm接收到請求時才會根據需求啟動php進程,最大為pm.max_children個,另外若php進程空閑時間達到pm.process_idle_timeout(單位s),就會kill掉該進程。 #有效配置:pm.max_children,pm.process_idle_timeout #3:dynamic,這種是最常用的,根據相關配置動態調整php進程個數; #有效配置如下: #pm.max_children : 最大php進程數; #pm.min_spare_servers:最小的空閑php進程數,少與該值會啟動php進程(這里的空閑并不是指完全空閑的php進程,可以直接理解為啟動的php進程就好了,把空閑二字去掉更貼切); #pm.max_spare_servers:最大的空閑php進程數,多余的會被kill; #pm.start_servers : php-fpm啟動時的php進程數,它的值需要在min_spare_servers和max_spare_servers之間,默認值:min_spare_servers(max_spare_servers - min_spare_servers) / 2; #pm.max_requests ,默認為0(此時等于PHP_FCGI_MAX_REQUESTS)。為了便于描述,此處假設它的值是500,那么這個參數的作用是一個php進程(即fpm的一個子進程)處理500個請求后會被kill,然后再啟動一個php進程,這樣可以防止因為內存泄漏導致的php進程占用內存過高的問題。 access.log = var/log/php-fpm/$pool-access.log #訪問文件日志; access.format = "%R - %u %t “%m %r%Q%q” %s %f %{mili}d %{kilo}M %C%%" #設定訪問日志的格式。 slowlog = /var/log/php-fpm/$pool-slow.log #慢請求日志; request_slowlog_timeout #默認為0(不啟用),此處假設它的值是10,則超過10s未響應的請求就是慢請求,會被記錄到慢請求日志中; request_terminate_timeout #默認為0(不啟用),此處假設它的值是20,則若某個請求超過20s未響應,相應的php進程會被kill掉,和php.ini中的max_execution_time效果類似。 php_value ,php_flag, php_admin_value , php_admin_flag #設置php.ini中的配置,后二者相比前兩者,不能被 PHP 代碼中的 ini_set() 及相似函數覆蓋。 #最重要的就是pm相關的幾個配置了,還有一些配置采用默認就好,詳情見官網。 【全局配置】 pid = run/php-fpm.pid #pid設置。 error_log = log/php-fpm.log #錯誤日志。 log_level = notice #錯誤級別。上面的php-fpm.log紀錄的錯誤等級。可用級別為:alert(必須立即處理),error(錯誤情況),warning(警告情況),notice(一般重要信息),debug(調試信息)。默認:notice。 syslog.facility = daemon #把日志寫進系統log,linux還不夠熟悉,暫時不用理會。 syslog.ident = php-fpm #系統日志標示(前綴),如果跑了多個fpm進程池,需要用這個來區分日志是誰的。 emergency_restart_threshold = 5 emergency_restart_interval = 60 #表示在60s內出現SIGSEGV或者SIGBUS錯誤的php-cgi進程數如果超過 emergency_restart_threshold個,php-fpm就會優雅重啟。這兩個選項一般保持默認值。0 表示‘關閉該功能’。默認值: 0 (關閉)。 process_control_timeout = 0 #設置子進程接受主進程復用信號的超時時間。可用單位:s(秒),m(分),h(小時),或者 d(天) 默認單位: s(秒)。默認值: 0。 process.max = 128 #當動態管理子進程時,fpm最多能fork多少個進程,默認0表示無限制,這是所有進程池能啟動子進程的總和,謹慎使用。 process.priority = -19 #設置子進程的優先級,在master進程以root用戶啟動時有效;如果沒有設置,子進程會繼承master進程的優先級,值范圍-19(最高)到20(最低),默認不設置。 rlimit_files = 1024 #設置master進程最多能打開的文件,默認為系統的值。 rlimit_core = 0 #master進程核心rlimit限制值;可選unlimited或>=0的整數,默認為系統的值。 events.mechanism = epoll #事件處理機制,默認自動檢測,可選值:select(any POSIX os), poll(any POSIX os), epoll(linux>=2.5.44), kqueue(FreeBSD >= 4.1,OpenBSD >= 2.9, NetBSD >= 2.0), /dev/poll(Solaris >= 7),port(Solaris >= 10)。linux>=2.5.44會默認epoll,效果最好的IO方式。 systemd_interval = 10s #當fpm被設置為系統服務時,多久向服務器報告一次狀態,單位有s,m,h。 daemonize = yes #作為守護進程運行php-fpm。默認值為yes。
問題未解決?付費解決問題加Q或微信 2589053300 (即Q號又微信號)右上方掃一掃可加博主微信
所寫所說,是心之所感,思之所悟,行之所得;文當無敷衍,落筆求簡潔。 以所舍,求所獲;有所依,方所成!