《大廠經(jīng)驗(yàn):兩步搞定PHP-FPM優(yōu)化,讓服務(wù)器更平穩(wěn)》要點(diǎn):
本文介紹了大廠經(jīng)驗(yàn):兩步搞定PHP-FPM優(yōu)化,讓服務(wù)器更平穩(wěn),希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
導(dǎo)言:Web服務(wù)器的CPU指標(biāo)和MEM指標(biāo)異常,不穩(wěn)定?可能是PHP-FPM進(jìn)程重啟機(jī)制的問(wèn)題導(dǎo)致的,一同和百度外賣探索下如何優(yōu)化吧.
猛哥
百度外賣基礎(chǔ)架構(gòu)部在線開發(fā)方向負(fù)責(zé)人
負(fù)責(zé)在線開發(fā)框架的持續(xù)優(yōu)化和長(zhǎng)期演進(jìn),主導(dǎo)研發(fā)的WFE/WODP/WOSP組成一套完整高效的WEB架構(gòu),支撐百度外賣所有在線服務(wù)高速高質(zhì)量地發(fā)展.百度外賣基礎(chǔ)架構(gòu)部在線開發(fā)團(tuán)隊(duì)
擅長(zhǎng)自底向上地創(chuàng)造和優(yōu)化基礎(chǔ)框架、基礎(chǔ)庫(kù)和基礎(chǔ)服務(wù),對(duì)NGINX和PHP有深層次的理解和創(chuàng)新性的改造.天下大事必作于細(xì),百度外賣基礎(chǔ)架構(gòu)部在線開發(fā)團(tuán)隊(duì),將持續(xù)精耕細(xì)作,適時(shí)發(fā)布成熟有效的在線服務(wù)優(yōu)化方案,期待與同行保持交流,共同進(jìn)步.
通過(guò)優(yōu)化PHP-FPM進(jìn)程重啟機(jī)制,改善線上服務(wù)器CPU_IDLE
和MEM_USED
波動(dòng)的問(wèn)題,使服務(wù)器資源利用率更加平滑可靠.
外賣交易服務(wù)集群報(bào)出在監(jiān)控圖上CPU_IDLE
波動(dòng)劇烈,如圖所示.
事實(shí)上一直以來(lái),不僅PU_IDLE
存在一定的波動(dòng),MEM_USED
的周期性斷崖式下降再回升也早已司空見慣.那么CPU_IDLE
與MEM_UESD
的波動(dòng)是否存在關(guān)聯(lián),追溯這種現(xiàn)象產(chǎn)生的原因,我們就必須理解PHP-FPM進(jìn)程管理器的機(jī)制.
在PHP5.3.3版本中,PHP-FPM正式被官方收編,作為FastCGI管理器,支持平滑停止啟動(dòng)進(jìn)程、slow-log、動(dòng)態(tài)進(jìn)程、運(yùn)行狀態(tài)等特性.
PHP-FPM進(jìn)程管理支持三種方式:static
、dynamic
、ondemand
.我們選用的是static
方式,即PHP-FPM生成固定數(shù)量的FastCGI進(jìn)程,這種方式比較簡(jiǎn)單,避免了頻繁開啟關(guān)閉進(jìn)程的開銷.(在線下虛擬機(jī)環(huán)境中,進(jìn)程管理可以配置成ondemand
,既降低了內(nèi)存需求又避免了進(jìn)程數(shù)量不夠用)
回到面臨的問(wèn)題上,CPU_IDLE
和MEM_USED
的周期性波動(dòng)是如何產(chǎn)生的.首先這是一種所有的集群都存在的現(xiàn)象,然后交易服務(wù)集群表現(xiàn)尤為突出.在排查了應(yīng)用程序(比如日志采集程序、定時(shí)腳本)的影響后,思路落在了PHP-FPM的一個(gè)關(guān)鍵參數(shù)上:max_requests
.
max_requests
這個(gè)參數(shù)使FastCGI進(jìn)程在處理一定數(shù)量的請(qǐng)求后自動(dòng)重啟,以此避免第三方擴(kuò)展內(nèi)存泄漏產(chǎn)生破壞性影響.打開線上配置,發(fā)現(xiàn)外賣交易服務(wù)集群中配置該參數(shù)過(guò)小,為1000,這便造成了在請(qǐng)求高峰期,FastCGI頻繁重啟,對(duì)CPU產(chǎn)生了負(fù)擔(dān).于是將max_requests
參數(shù)調(diào)整為10000后,CPU_IDLE
表現(xiàn)得到了改善,如圖.
但是經(jīng)過(guò)觀察發(fā)現(xiàn),CPU_IDLE
和MEM_USED
周期性波動(dòng)的問(wèn)題并沒有根除,效果如圖.
這很好理解,我們調(diào)大max_requests
參數(shù),但是FastCGI重啟機(jī)制依然生效,每個(gè)請(qǐng)求都會(huì)計(jì)數(shù),當(dāng)計(jì)數(shù)到達(dá)max_request
之后,cgi進(jìn)程會(huì)執(zhí)行 fcgi_finish_request
退出進(jìn)程,子進(jìn)程退出,fpm-master
進(jìn)程會(huì)收到SIGCHLD信號(hào),運(yùn)行fpm_children_bury
重啟進(jìn)程,重啟的方式是fork一個(gè)子進(jìn)程.
FastCGI進(jìn)程通過(guò)unix socket承接Nginx請(qǐng)求,負(fù)載較為均衡,生產(chǎn)環(huán)境流量大,PHP進(jìn)程數(shù)配置較大,數(shù)以百計(jì)的FastCGI會(huì)在同一時(shí)間到達(dá) max_requests
上限而進(jìn)行重啟,這便造成了CPU_IDLE
和MEM_USED
周期性波動(dòng).
max_requests
的初衷是為了避免第三方擴(kuò)展引起的內(nèi)存泄漏問(wèn)題,雖然線上環(huán)境使用的擴(kuò)展經(jīng)過(guò)分析和測(cè)試,并沒有嚴(yán)重的內(nèi)存泄漏問(wèn)題,但是由于擴(kuò)展內(nèi)部使用的第三方庫(kù)太多,并無(wú)法完全避免內(nèi)存泄漏問(wèn)題,同時(shí)max_requests
機(jī)制很適合FastCGI多進(jìn)程環(huán)境,以較小的代價(jià),換取內(nèi)存泄漏的長(zhǎng)治久安.
為了避免CPU_IDLE
和MEM_USED
周期波動(dòng),同時(shí)保持max_requests
機(jī)制,需要在PHP-FPM源碼上稍作修改.FastCGI進(jìn)程在啟動(dòng)時(shí),設(shè)置max_requests
,此時(shí)只要將max_requests
配置參數(shù)散列開,使FastCGI進(jìn)程分別配置不同的值,即可達(dá)到效果.
具體代碼在sapi/fpm/fpm/fpm.c
,修改如下:
php_mt_srand(GENERATE_SEED()); *max_requests=fpm_globals.max_requests+php_mt_rand()&8191;
經(jīng)過(guò)修改上線,對(duì)比效果見下圖
至此CPU_IDLE
和MEM_USED
已經(jīng)告別了周期性波動(dòng),避免了CPU計(jì)算資源產(chǎn)生浪涌效果,內(nèi)存占用數(shù)據(jù)也更加真實(shí)可靠.
以此文拋磚引玉,PHP-FPM在生產(chǎn)環(huán)境的精細(xì)優(yōu)化,任重而道遠(yuǎn).
文章來(lái)自微信公眾號(hào):高效運(yùn)維
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/1977.html