您好,登錄后才能下訂單哦!
小編給大家分享一下高性能優(yōu)化PHP-FPM是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
PHP是無(wú)處不在的,可以說(shuō)是互聯(lián)網(wǎng) Web 應(yīng)用上使用最廣泛的語(yǔ)言。
然而,它的高性能并不為人所知,尤其是在涉及到高并發(fā)系統(tǒng)時(shí)。這就是為什么對(duì)于這樣特殊的用例,正在被 Node (是的,我知道,它不是一種語(yǔ)言)、Go 和 Elixir 等語(yǔ)言接管。
也就是說(shuō),您可以做很多事情來(lái)改進(jìn)服務(wù)器上的 PHP 性能。本文主要關(guān)注 php-fpm
方面的內(nèi)容,如果您使用Nginx,這是在服務(wù)器上的默認(rèn)配置。
如果你知道 php-fpm
是什么,請(qǐng)直接跳到優(yōu)化部分。
許多開(kāi)發(fā)人員對(duì) DevOps 方面的知識(shí)不太感興趣,即使是那些對(duì)此感興趣的開(kāi)發(fā)人員,也極少有人知道它的底層原理。有趣的是,當(dāng)瀏覽器發(fā)送一個(gè)請(qǐng)求到運(yùn)行 PHP 的服務(wù)器上時(shí),PHP 也不是最先進(jìn)行處理請(qǐng)求的服務(wù);而是,HTTP 服務(wù)器,Apache 和 Nginx 是其中最主要的兩個(gè)?!竪eb 服務(wù)器」決定如何與 PHP 進(jìn)行通信,然后傳遞請(qǐng)求的類(lèi)型,數(shù)據(jù)和頭部信息到 PHP 進(jìn)程。
上圖是 PHP 項(xiàng)目的請(qǐng)求-響應(yīng)生命周期(圖片來(lái)源: ProinerTech)
在現(xiàn)代 PHP 應(yīng)用中,「find file」部分即為 index.php
文件,它是在服務(wù)器配置文件中配置的用于處理所有請(qǐng)求的代理。
如今,Web 服務(wù)器究竟如何連接 PHP 正在進(jìn)化,如果我們要深入研究所有細(xì)節(jié),這篇文章的長(zhǎng)度將激增。但粗略來(lái)說(shuō), 在 Apache 作為 Web 服務(wù)器首選的時(shí)間段,PHP 是作為包含在服務(wù)器內(nèi)部的模塊。
所以每當(dāng)一個(gè)請(qǐng)求被接收,服務(wù)器將開(kāi)啟一個(gè)新的進(jìn)程, 它將自動(dòng)包含 PHP 和執(zhí)行請(qǐng)求。這個(gè)方法被稱(chēng)作mod_php
,“PHP作為一個(gè)模塊”的縮寫(xiě)。這種方法有其局限性,而 Nginx 和 php-fpm
克服了它。
在php-fpm
中,管理 PHP 的責(zé)任在于服務(wù)器內(nèi)部的 PHP 程序。換言之, Web 服務(wù)器 (Nginx, 在本例中), 不在乎 PHP 在哪和怎樣運(yùn)行的,只要它知道如何發(fā)送和接收數(shù)據(jù)即可。如果需要,在這種情況下,您可以將PHP視為另一臺(tái)服務(wù)器,它管理傳入請(qǐng)求的某些子PHP進(jìn)程(因此,我們將請(qǐng)求送到服務(wù)器,該請(qǐng)求由服務(wù)器接收并傳遞到服務(wù)器 — —太瘋狂了!:-P)。
如果你用過(guò)Nginx
,你會(huì)看到這些代碼:
location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php/php7.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
對(duì)于這一行:fastcgi_pass unix:/run/php/php7.2-fpm.sock;
,它告訴Nginx通過(guò) php7.2-fpm.sock
的socket
與php進(jìn)程通信。因此,對(duì)于每個(gè)傳入的請(qǐng)求,Nginx都通過(guò)這個(gè)文件寫(xiě)入數(shù)據(jù),在接收到輸出后,將其發(fā)送回瀏覽器。
我必須再次強(qiáng)調(diào),對(duì)于如何運(yùn)行這不是最完整或者最準(zhǔn)確的,但對(duì)于大多數(shù) DevOps 任務(wù)是完全準(zhǔn)確的。
除此之外,讓我們回顧一下到目前為止所學(xué)到的東西:
流程圖如下:
PHP 和 Nginx 如何協(xié)同工作? (圖片來(lái)源:數(shù)據(jù)狗)
到目前為止都不錯(cuò), 那么關(guān)鍵問(wèn)題來(lái)了:PHP-FPM到底是什么呢?
PHP 中的 FPM
代表 「快速進(jìn)程管理器」, 花式解釋就是說(shuō),在服務(wù)器上運(yùn)行的 PHP 并不是單個(gè)進(jìn)程,而是由這個(gè) FPM 進(jìn)程管理器派生、控制和終止的一些PHP 進(jìn)程。web服務(wù)器將請(qǐng)求傳遞給的就是這個(gè)進(jìn)程管理器。
PHP-FPM 本身就是一個(gè)完整的兔子洞,所以如果您愿意,可以隨意探索,但是對(duì)于我們的目的,這些解釋就足夠啦。 ?
一般在正常運(yùn)行的情況下,為什么要考慮優(yōu)化呢? 為什么不將事物保持原樣。
具有諷刺意味的是,一般我為大多數(shù)用例提供建議的話(huà)。 如果您的設(shè)置運(yùn)行良好,并且沒(méi)有特殊用例,請(qǐng)使用默認(rèn)設(shè)置。 但是,如果您希望擴(kuò)展一臺(tái)機(jī)器之外的能力,那么從一臺(tái)機(jī)器中擠出最大的處理能力是必不可少的,因?yàn)樗梢詫⒛?wù)器的花費(fèi)減少一半(甚至更多!)。
要說(shuō)明的另一件事情是,Nginx是為處理巨大的工作負(fù)載而構(gòu)建的。 它能夠同時(shí)處理成千上萬(wàn)的連接,但是如果您的PHP設(shè)置不合理,那么您將浪費(fèi)很多資源,因?yàn)镹ginx必須等待PHP完成當(dāng)前處理之后才可以接受下一個(gè)請(qǐng)求,最終Nginx不能為您的服務(wù)提供任何優(yōu)勢(shì)!
所以,接下來(lái)讓我們看看嘗試優(yōu)化 php-fpm
時(shí)我們到底要優(yōu)化什么。
php-fpm
的配置文件在不同服務(wù)器上的位置可能不同,因此您需要做一些調(diào)查來(lái)確定它的位置。在 UNIX 上,你可以使用 find 命令。在我的 Ubuntu 上,它的路徑是 /etc/php/7.2/fpm/php-fpm.conf
。當(dāng)然,7.2是我正在運(yùn)行的 PHP 版本。
下面是這個(gè)文件的前幾行代碼:
;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; All relative paths in this configuration file are relative to PHP's install ; prefix (/usr). This prefix can be dynamically changed by using the ; '-p' argument from the command line. ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] ; Pid file ; Note: the default prefix is /var ; Default Value: none pid = /run/php/php7.2-fpm.pid ; Error log file ; If it's set to "syslog", log is sent to syslogd instead of being written ; into a local file. ; Note: the default prefix is /var ; Default Value: log/php-fpm.log error_log = /var/log/php7.2-fpm.log
很明顯:這一行 pid = /run/php/php7.2-fpm.pid
告訴我們哪個(gè)文件包含了 php-fpm
進(jìn)程的進(jìn)程 id。
我們還看到 /var/log/php7.2-fpm.log
是 php-fpm
存儲(chǔ)日志的地方。
在這個(gè)文件中,像下面這樣添加三個(gè)變量:
emergency_restart_threshold 10 emergency_restart_interval 1m process_control_timeout 10s
前兩個(gè)設(shè)置是警告性的,它們告訴 php-fpm
進(jìn)程,如果10個(gè)子進(jìn)程在一分鐘內(nèi)失敗,主 php-fpm
進(jìn)程應(yīng)該重新啟動(dòng)自己。
這聽(tīng)起來(lái)可能不夠穩(wěn)健,但是 PHP 是一個(gè)短暫的進(jìn)程,它會(huì)泄漏內(nèi)存,所以在出現(xiàn)高故障時(shí)重新啟動(dòng)主進(jìn)程可以解決很多問(wèn)題。
第三個(gè)選項(xiàng)是 process_control_timeout
,它告訴子進(jìn)程在執(zhí)行從父進(jìn)程接收到的信號(hào)之前需要等待這么長(zhǎng)的時(shí)間。這個(gè)設(shè)置是非常有用的。例如,當(dāng)父進(jìn)程發(fā)送終止信號(hào)時(shí),子進(jìn)程正在處理某些事情的時(shí)候。十秒的時(shí)間,他們會(huì)有一個(gè)更好的機(jī)會(huì)完成任務(wù)并且優(yōu)雅地退出。
令人驚訝的是,這 不是 php-fpm 的核心配置!這是因?yàn)?,為?web 請(qǐng)求服務(wù),php-fpm
創(chuàng)建了一個(gè)新的進(jìn)程池,它將具有一個(gè)單獨(dú)的配置。在我的例子中,進(jìn)程池的名稱(chēng)是 www
,我想編輯的文件是 /etc/php/7.2/fpm/pool.d/www.conf
。
讓我們來(lái)看看文件的內(nèi)容:
; Start a new pool named 'www'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) [www] ; Per pool prefix ; It only applies on the following directives: ; - 'access.log' ; - 'slowlog' ; - 'listen' (unixsocket) ; - 'chroot' ; - 'chdir' ; - 'php_values' ; - 'php_admin_values' ; When not set, the global prefix (or /usr) applies instead. ; Note: This directive can also be relative to the global prefix. ; Default Value: none ;prefix = /path/to/pools/$pool ; Unix user/group of processes ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. user = www-data group = www-data
快速瀏覽一下上面代碼片段的末尾,您就會(huì)明白為什么服務(wù)器進(jìn)程以 www-data
的形式運(yùn)行了。如果您在設(shè)置網(wǎng)站時(shí)遇到文件權(quán)限問(wèn)題,您可能要將目錄的所有者或組更改為 www-data
,從而允許PHP進(jìn)程寫(xiě)入日志文件和上傳文檔等。
最后,我們到達(dá)了問(wèn)題的根源,流程管理器 (pm) 設(shè)置。一般情況下,默認(rèn)值是這樣的:
pm = dynamic pm.max_children = 5 pm.start_servers = 3 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 200
那么,這里的 「dynamic(動(dòng)態(tài))」是什么意思呢?我認(rèn)為官方文檔最好地解釋了這一點(diǎn)(我的意思是,這應(yīng)該已經(jīng)是您正在編輯的文件的一部分,但是我在這里復(fù)制了它,以防它不是):
; Choose how the process manager will control the number of child processes. ; Possible Values: ; static - a fixed number (pm.max_children) of child processes; ; dynamic - the number of child processes are set dynamically based on the ; following directives. With this process management, there will be ; always at least 1 children. ; pm.max_children - the maximum number of children that can ; be alive at the same time. ; pm.start_servers - the number of children created on startup. ; pm.min_spare_servers - the minimum number of children in 'idle' ; state (waiting to process). If the number ; of 'idle' processes is less than this ; number then some children will be created. ; pm.max_spare_servers - the maximum number of children in 'idle' ; state (waiting to process). If the number ; of 'idle' processes is greater than this ; number then some children will be killed. ; ondemand - no children are created at startup. Children will be forked when ; new requests will connect. The following parameter are used: ; pm.max_children - the maximum number of children that ; can be alive at the same time. ; pm.process_idle_timeout - The number of seconds after which ; an idle process will be killed. ; Note: This value is mandatory.
由此可見(jiàn),有三個(gè)可用值:
php-fpm
在任何給定時(shí)間點(diǎn)會(huì)保持活動(dòng)的最小以及最大進(jìn)程數(shù)量。那這些設(shè)置有什么影響呢?
簡(jiǎn)而言之,如果你有個(gè)小流量的網(wǎng)站,“dynamic”設(shè)置在大多數(shù)時(shí)間內(nèi)都是一種資源的浪費(fèi)。假設(shè)你的pm.min_spare_servers
設(shè)置成了3,那會(huì)有三個(gè)PHP進(jìn)程會(huì)被創(chuàng)建并保持運(yùn)行,甚至是網(wǎng)站沒(méi)有流量時(shí)。這種情況下,“ondemand” 就是個(gè)更好的選擇, 可以讓系統(tǒng)決定何時(shí)啟動(dòng)新的進(jìn)程。
另一方面, 大流量 或者必須快速響應(yīng)的網(wǎng)站將在這種情況下被懲罰。 最好避免創(chuàng)建新的 PHP 進(jìn)程的額外開(kāi)銷(xiāo),使其成為池的一部分并對(duì)其進(jìn)行監(jiān)控。
使用 pm = static
固定子進(jìn)程的數(shù)量,使最大的系統(tǒng)資源用于服務(wù)請(qǐng)求而不是管理 PHP。假如你確定走這條路,注意它有其指導(dǎo)方針和陷阱.
以上是高性能優(yōu)化PHP-FPM是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。