深入瞭解怎麼優化php+php-fom+nginx設定引數

2022-03-04 16:00:30
怎麼優化php+php-fom+nginx設定引數?下面本篇文章給大家詳細介紹一下php+php-fom+nginx設定引數調優的方法,希望對大家有所幫助。

一、前言

對於一臺新的伺服器,安裝LNMP環境只是第一步,第二步當然是要修改預設的設定引數,讓這些程式變得好用,效能也提升起來。這篇文章主要講述php+php-fpm+nginx的設定引數,機器是4GB記憶體的伺服器,相關設定都是按照4GB記憶體的伺服器來設定的。

1、mysql設定引數:

mysql設定引數調優(8GB記憶體和64GB記憶體)
mysql組態檔構成以及具體的設定demo

2、注意

下面給出的一些設定都是相對來說會影響效能或者必須要設定的地方,沒有提及的設定都是按照預設的來。這三個程式的設定引數很多,咱們的伺服器剛開始也著實用不到太複雜的設定,下面的設定主要是為了儘量提升高並行能力以及儘量提高程式的效能。

php和php-fpm都是5.6版本的。(一切都是為了相容老專案,,苦逼)

二、php引數設定及講解

1、phpini的基本設定

(1)safe_mode  這份的設定採用預設的
(2)disable_functions  在預設的基礎上,加上eval()函數
(3)expose_php = off
(4)register_globals和magic_quotes_gpc引數都在php5.4.0後被移除了
(5)錯誤提示以及紀錄檔部分採用預設的就行,現在大部分使用的都是框架,
檢視框架的錯誤紀錄檔更方便

這幾個引數是網上經常提及的,不過咱們這邊並不是都要按照他們的設定來,畢竟年代已久,很多bug或者效能問題都已經被修復。

2、php引數設定

(1)max_execution_time = 300

指令碼執行的最長時間,超出規定時間,指令碼會自動殺死這個請求,為了能上傳大檔案,所以這個值設定的大一些。這個值太小也會造成程式502錯誤。

(2)memory_limit = 128M

每個指令碼使用的最大記憶體

(3)max_inpit_time = 300

每個指令碼等待輸入資料的最長時間

(4)upload_max_filesize = 20M

上傳檔案的最大許可大小

(5)allow_url_fopen = off

禁止開啟遠端地址

(6)post_max_size = 20M
post上傳的大小,要>=upload_max_filesize

(7);cgi.fix_pathinfo=1
預設開啟,目前高版本的php已經避免了這個漏洞,php-fpmsecurity.limit_extensions 預設值早就是 .php了。所以咱們這個引數使用預設的就行。
參考:php fpm 設定項 cgi.fix_pathinfo=1 漏洞不再出現

關於php.ini,要設定的引數就是這些了,主要是增加程式的執行時間,增加上傳檔案大小等,可以方便我們平時的php開發。

三、php-fpm設定

1、設定子程序數,增加並行量

log_level = notice		//notice級別的紀錄檔,預設的
rlimit_files = 4048		//調整最大開啟檔案數量
pm選用動態變化的dynamic

process.max = 150		// 最大子程序,設定成和max_children一樣就行
pm = dynamic
pm.max_children = 150	//最大子程序,假如一個程序30M,4G記憶體的話最大為:4048/30 = 135,取150
pm.start_servers = 20
pm.min_spare_servers = 6
pm.max_spare_serveres = 30   
//計算公式是:min_spare_servers ≤ start_servers ≤ max_spare_servers ≤ max_children

這塊很多人都建議,如果你的記憶體比較大,那麼設定靜態的pm = static,這個時候,起作用的只有max_children引數,初始的時候就有max_children個程序,剛開始一個php-fpm程序只佔用3M左右記憶體,我們4GB的機器按照一個程序20M計算,可以設定max_children200或者150。如果是專門的php伺服器,建議是設定為靜態的,效能最佳。

如果設定成動態的也可以,這樣的話是start_servers等程式起作用,會隨著業務的增加而不斷新增程序,不過最大程序數是不能超過max_children的。博主這邊考慮到機器記憶體小而且機器上還跑了mysqlredis等,還是選用了動態的,這樣一開始不會有很大的壓力,等存取量上來了,可能會修改為靜態的。

2、防止頻繁出現502錯誤

(1)process_control_timeout = 20

php-fpm給子程序分配的時間間隔

(2)request_terminate_timeout = 320s

表示等待320秒後,結束那些沒有自動結束的php指令碼,以釋放佔用的資源。設定320s主要是因為php的程式執行時間是300s,所以對於php-fpm來說,這個值應該是大於php指令碼規定的執行時間的(因為php指令碼的執行可能還會帶有mysql服務或者其他的一些服務,這個引數是殺掉這個程序,包括著純php指令碼以及其他服務)。

(3)自動重新啟動設定

#表示在emergency_restart_interval所設值內出現SIGSEGV或者SIGBUS錯誤的php-cgi程序數如果
#超過emergency_restart_threshold個php-fpm就會優雅重新啟動。這兩個選項一般保持預設值

emergency_restart_threshold = 30
emergency_restart_interval = 60s	//一分鐘內出現30次上述訊號即重新啟動php-fpm

(4)pm.max_requests = 1000

每一個子程序的最大請求服務數量,如果超過了這個值,該子程序會被自動重新啟動。

比如max_requests這個引數,如果設定很大的話,那這個子程序要執行很多次才會重新啟動,假如這個請求發生了錯誤或者記憶體漏失,那麼這個值設定很大是不合適的。但如果請求沒有問題,這個值設定小的話就會頻繁的重新啟動,這樣也會碰到不少502的問題,所以要仁者見仁,智者見智的設定了,這裡初始化設定1000,如果測試沒有記憶體漏失等問題,可以再大一些。

3、php-fpm中的慢紀錄檔設定

mysql中有慢紀錄檔這個概念,可以記錄查詢速度比較慢的sql,同樣的,php-fpm也可以開啟慢紀錄檔,記錄執行速度比較慢的php請求,方便我們後續的偵錯和優化。

(1)慢紀錄檔的主要引數

request_slowlog_timeout : 預設是註釋的,開啟註釋,設定為1,代表請求超過1s,就會記錄這個指令碼到慢紀錄檔檔案中。也可以的更大,按照需求來。
slowlog : 預設也是註釋的,可以開啟註釋使用預設的慢紀錄檔路徑,也可以自定義路徑。

這裡開啟慢紀錄檔,如下:

request_slowlog_timeout = 2   # 記錄超過2s的請求
slowlog = /var/log/php-fpm/www-slow.log	#慢紀錄檔路徑

(2)利用sort/uniq命令分析彙總php-fpm慢紀錄檔:

grep -v 「^$」 www.log.slow.tmp | cut -d 」 」 -f 3,2 | sort | uniq -c | sort -k1,1nr | head -n 50

引數解釋:

sort: 對單詞進行排序
uniq -c: 顯示唯一的行,並在每行行首加上本行在檔案中出現的次數
sort -k1,1nr: 按照第一個欄位,數值排序,且為逆序
head -10: 取前10行資料

4、php-fpm中的backlog是幹啥的?

如果worker程序不夠用,master程序會prefork更多程序,如果prefork達到了pm.max_children上限,worker程序又全都繁忙,這時master程序會把請求掛起到連線佇列backlog裡,而backlog預設值是511,除了加大pm.max_children,調整backlog也是有必要的。

也就說這個backlog是在優化高並行的時候必須要設定的,這個值的大小和fpmqps也有關。backlog太大,fpm處理不過來照樣會報錯504(超時)。這個對於目前的機器來說,我設定的max_children = 150,然而backlog的預設值是511,所以在短期內是完全夠用的,不過也可以在php-fpm.conf裡面顯式的制定backlog的值,比如制定:listen.backlog = 1024 #2的n次冪

參考:

PHP引數調優
nginx報錯502:connect() to unix:/var/run/php5-fpm.sock failed (2: No such file or directory)
php-fpm程序數管理
關於PHP-FPM的backlog的預設值
PHP-FPM中backlog引數變更的一些思考
PHP-fpm

四、nginx設定引數調優

1、nginx中的一些層級關係

一般開啟nginx組態檔,會發現有httpserver,location等,那麼他們的層級關係是什麼樣的呢?

答案是: 一個http裡面可以有多個server,一個server裡面可以有多個location

我們設定的時候,各個server共用的部分可以設定在http模組裡面。每個server自己特有的一些部分,按照各自的需求設定在server模組裡面。同樣的,對於location是分的更細的,按照每個server的每個location需求來設定。

其次是如果在conf.d資料夾下有其他的組態檔,那麼我們的nginx.conf就是公用的組態檔了,一些公用的部分都可以設定在nginx.conf檔案中,各個站點特殊的設定就放在conf.d檔案下。

參考:
nginx短篇(4):模組、設定指令、塊之間的關係

2、nginx.conf 範例及解釋

user www-data;
worker_processes auto; #自動檢測CPU的核數
worker_rlimit_nofile 65535;  #worker程序的最大開啟檔案數限制
error_log   /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
pid /run/nginx.pid;

events {
    worker_connections  10240;  #子程序最大連線數,總連線數:worker_processes * worker_connections
    use epoll; #使用epoll模型
}

http {
    include       mime.types; # #副檔名與檔案型別對映表
    default_type  application/octet-stream;  #這個型別會讓瀏覽器認為響應是普通的檔案流,並提示使用者下載檔案

        #記錄都有哪些變數可以記錄到log_format
        log_format  main  '$remote_addr $host $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_accept_language" "$request_time" '
                      '"$upstream_response_time" "$upstream_addr" "$upstream_status" "$http_x_real_ip" "$proxy_add_x_forwarded_for"';

    sendfile        on;  #立即將資料從磁碟讀到OS快取
    tcp_nopush      on;  #告訴nginx在一個封包裡傳送所有標頭檔案
    tcp_nodelay     on;  # 告訴nginx不要快取資料,而是一段一段的傳送
    keepalive_timeout  30; #伺服器將在這個超時時間過後關閉連結
    types_hash_max_size 2014;

    #resolver xxx;  #用於解析上游伺服器名稱的名稱伺服器設定到地址中
    gzip_static on;
    gzip  on;
    gzip_http_version 1.1;
    gzip_vary off;
    gzip_comp_level 4;  #資料的壓縮等級,9是最慢但是壓縮比最大的
    gzip_proxied off;
    gzip_buffers 16 8k;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";
    #設定需要壓縮的資料格式
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/hero-res;

    client_max_body_size 20m;  #設定網頁上傳檔案的最大值,和php.ini中的上傳設定保持一致
    server_names_hash_max_size 2048;  #儲存伺服器名字的hash表

    include /etc/nginx/client.conf;
    include /etc/nginx/conf.d/*.conf;
}

(1)worker_rlimit_nofile

更改worker程序的最大開啟檔案數限制。

檢視當前程序可以開啟的檔案數:

ulimit-n			
//結果:65535

檢視當前系統可以開啟的最大檔案數:

ljf@hx:cat /proc/sys/fs/file-max
813544

(2)log_format中的內容

參考官網:https://nginx.org/en/docs/http/ngx_http_core_module.html#var_status

remote_addr:對應使用者端的地址
remote_user:是請求使用者端請求認證的使用者名稱,如果沒有開啟認證模組的話是值為空。
time_local:表示nginx伺服器時間
request:表示request請求頭的行
status:表示response的返回狀態
body_bytes_sent:表示從伺服器端返回給使用者端的body資料大小
http_referer:表示請求的上一級頁面
http_user_agent:表示agent資訊
http_x_forwarded_for:會記錄每一級請求中資訊

(3)gzip壓縮相關解釋

參考:https://www.jb51.net/article/95041.htm

(4)client_max_body_size設定

這個引數規定使用者端上傳的body的最大值,和php.ini中的最大上傳數保持一致,不然的話,就算php.ini設定上傳的最大檔案是1G,如果nginx
不設定這個引數的話,那麼上傳一樣會報錯的。

3、對於conf.d資料夾中的設定

(1)設定範例程式碼

server{
      listen IP:80;
    server_name xxx;
    access_log  /var/log/nginx/access.log;  #access紀錄檔

    fastcgi_intercept_errors on; #支援nginx404重定向

    index index.php index.html  index.htm;

    root /product/ucool/production/manage/htdocs/backend/web/;

        send_timeout 15;
        #使用者端與伺服器建立連線後傳送request body的超時時間(小於keepalive_timeout)
        client_body_timeout 20;
        #使用者端向伺服器傳送一個完整的request header的超時時間(小於keepalive_timeout)
        client_header_timeout 20;
        fastcgi_connect_timeout         300;    #指定連線到後端FastCGI的超時時間
        fastcgi_send_timeout            300;    #指定向FastCGI傳送請求的超時時間
        fastcgi_read_timeout            300;    #指定接收FastCGI應答的超時時間
        fastcgi_buffer_size 64k;               #指定讀取FastCGI應答第一部分需要用多大的緩衝區
        fastcgi_buffers 4 64k;                 #定本地需要用多少和多大的緩衝區來緩衝FastCGI的應答請求


      location ~* ^.+\.(git|svn|sql|bak|old|rar|tgz|7z|bz2|tar|idea)$ {
        return 404;
      }
      location ~ \.php$ {
                fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
                include fastcgi_params;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
        location ~ /\.git { deny all; }
}

(2)主要是fastcgi的一些設定

這裡不考慮負載均衡和反向代理,關於fastcgi的優化可以參考:

https://www.jb51.net/article/145222.htm

(3)關於send_timeout

    send_timeout 15;
    #使用者端與伺服器建立連線後傳送request body的超時時間(小於keepalive_timeout)
    client_body_timeout 20;
    #使用者端向伺服器傳送一個完整的request header的超時時間(小於keepalive_timeout)
    client_header_timeout 20;

這幾個引數最好是再小一些,包括keepalive_timeout,小一些的話,能處理更多的有效請求,有利於提升nginx的處理效能,大佬們的設定如下:

client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;

4、儲存編輯之後檢查組態檔的正確性

(1)檢查組態檔是否正確

ljf@hx:/etc/nginx$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

返回successful並且沒有報錯資訊的話,說明組態檔裡面的語法是沒問題的,如果報錯了那就是語法出錯了,導致設定無法正常讀取。

(2)檢查子級組態檔是否正確

nginx -t -c /etc/nginx/conf.d/xxx.conf

例如:

ljf@hx:/etc/nginx$ sudo nginx -t -c /etc/nginx/conf.d/api.conf
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/conf.d/api.conf:1
nginx: configuration file /etc/nginx/conf.d/api.conf test failed

很明顯組態檔是錯的。

五、影響程式超時的引數

php.ini中有max_execution_time 引數。
php-fpm中有request_terminate_timeout引數
nginx.conf中有 fastcgi_connect_timeout 等引數。

1、關於php和php-fpm超時時間的設定

首先是max_execution_time 這個值限定了指令碼的最大執行時間,但是僅限於php指令碼,對於指令碼中的流操作和資料庫操作等耗費的時間是不算進去的。而php-fpmrequest_terminate_timeout 代表單個請求的超時中止時間,並不會受其他指令碼影響,定義10s結束,那麼10s就準時結束該php指令碼的執行。所以設定超時時間的時候,request_terminate_timeout 可以比max_execution_time 稍微大一些。

還有一種說法,在伺服器正常執行的時候,php-fpm.conf中的request_terminate_timeout 會覆蓋php.ini中的max_execution_time,所以request_terminate_timeout 的值更代表我們對於指令碼執行時間的預期。如果伺服器效能足夠好,可以設定request_terminate_timeout = 0代表永不超時。

當程式執行時間大於規定的引數的時候,php-fpm會終止該php子程序。

2、nginx中的超時設定

nginxfastcgi_connect_timeout 操作影響的是ningx的超時,一般來說,如果是php或者php-fpm超時,那麼報錯502 Bad Gateway(閘道器錯誤) 。如果是nginx超時的話,報錯是:504 Gateway Time-out (閘道器超時) ,到時候我們可以根據這個報錯資訊來定位問題。一般來說,為防止頻繁的出現超時錯誤,設定fastcgi_connect_timeout 相關時間為300s是合適的。

假如設定fastcgi_read_timeout=10test.php執行時間100秒,則10秒後webserver會關閉和PHP的連線。也就是說當程式執行時間大於規定的引數的時候,webserver會關閉和PHP的連線,出現超時錯誤。所以這個fastcgi的超時時間最好是和php-fpm中的request_terminate_timeout 保持一致。

3、nginx中的keepalive_timeout

keepalive_timeout引數是一個請求完成之後還要保持連線多久,不是請求時間多久,目的是保持長連線,減少建立連線過程給系統帶來的效能損耗,類似於執行緒池,資料庫連線池。

4、總結

對於程式超時時間來說,並不能單純的設定php或者設定php-fpm就能完全解決這個問題。因為它們是協調工作的,所以設定這幾個引數的時候是要相互考慮的,防止因為木桶原理,最低的那個板子影響系統的效能。

以上就是對於php+php-fpm+nginx的引數調優,這些設定在我本地都是設定過的,並沒有什麼問題,修改的值也是儘可能的發揮咱們伺服器的效能。實際的效果還要放到生產環境來檢驗,不過肯定是比預設的設定效能好滴。

後續我也會不斷根據生產環境的反饋來更新這些引數,如果各位大佬有好意見或者不同的看法,歡迎溝通交流~

end

推薦學習:《》

以上就是深入瞭解怎麼優化php+php-fom+nginx設定引數的詳細內容,更多請關注TW511.COM其它相關文章!