前段時間骇窍,網(wǎng)站突然開始出現(xiàn)502镐确。第一想法可能是QPS突然飆升,導(dǎo)致服務(wù)器迎接不暇饼煞;遂立馬登上服務(wù)器加大fpm進(jìn)程數(shù)源葫;話說回來如果加大進(jìn)程數(shù)能解決問題的話,這也是當(dāng)前最快的問題解決方式砖瞧。并在心中不由的一喜息堂,難道網(wǎng)站訪問量突然上升,我們要迎來高并發(fā)了嗎块促?本人一直想實(shí)際的接觸和解決高并發(fā)問題荣堰,然后像各位大神那樣去分享一波經(jīng)驗(yàn);此處應(yīng)有一波自豪而又邪惡的表情竭翠,哈哈哈...
然而問題并沒有因?yàn)樘砑舆M(jìn)程數(shù)而得到真正解決振坚。在剛添加進(jìn)程數(shù)時,情況確實(shí)有所改善斋扰。但短暫的十幾分鐘后渡八,就又開始出現(xiàn)問題了。由于返回的是nginx的502錯誤頁面传货,我們也就首先查看nginx的日志屎鳍。跟蹤到錯誤信息確實(shí)是nginx在代理fpm處理時出現(xiàn)超時。那么確實(shí)印證了fpm抗QPS能力不足的問題问裕。遂繼續(xù)加大fpm進(jìn)程數(shù)逮壁,此時fpm進(jìn)程數(shù)已經(jīng)擴(kuò)大10倍了。由于原先站點(diǎn)訪問量一般粮宛,并且當(dāng)前服務(wù)器只處理動態(tài)頁面和數(shù)據(jù)接口窥淆,其他文件資源全部走的CDN和云存儲;那么最初的fpm進(jìn)程數(shù)只開了20巍杈,在相當(dāng)長的一段時間里也沒出現(xiàn)什么問題忧饭。確實(shí)也是訪問量沒上來,QPS最高也就一百出頭(^_^)a秉氧。加到200進(jìn)程數(shù)后眷昆,當(dāng)前確實(shí)沒有再收到502的情況反饋。當(dāng)前問題算是解了汁咏。
但回過頭來去查看問題時候亚斋,發(fā)現(xiàn)QPS并沒有想象中爆發(fā)的那么厲害,最大QPS也才100多攘滩!那么問題來了帅刊,是什么情況導(dǎo)致PHP進(jìn)程被占用而無法應(yīng)對100多的QPS呢?
總的來說可以歸結(jié)于單個PHP請求處理時間太長漂问;當(dāng)多數(shù)fpm進(jìn)程被長時間處理的請求占用時赖瞒,整個站點(diǎn)的抗QPS能力就下降了女揭。當(dāng)降到無法抗住當(dāng)前QPS時,就開始頻繁的502了栏饮。
由于系統(tǒng)較復(fù)雜吧兔,想直接找出慢執(zhí)行的請求的代碼并不容易。這時袍嬉,fpm的slowlog功能價值就體現(xiàn)出來了境蔼。設(shè)置slowlog的timeout時間,并設(shè)計(jì)存放log路徑伺通。紀(jì)錄能直接精確到方法箍土,還是很贊的。然后對著紀(jì)錄結(jié)果去優(yōu)化對應(yīng)的程序邏輯代碼吧罐监!
由于調(diào)整業(yè)務(wù)邏輯以及一些詳細(xì)的優(yōu)化策略都需要相對較長的時間吴藻,那么當(dāng)前可以先進(jìn)行一些fpm調(diào)整。上述加大進(jìn)程數(shù)是一個弓柱,但一臺機(jī)器的最大進(jìn)程數(shù)還是有上限的沟堡。那么為了不讓慢執(zhí)行長時間占用進(jìn)程,設(shè)置fpm的request_terminate_timeout吆你。由于我們站點(diǎn)基本沒有特意需要長時間執(zhí)行PHP的業(yè)務(wù)弦叶,那么就可以選擇降低這個值俊犯。直接設(shè)置成5s妇多,當(dāng)超出5秒無法處理完直接結(jié)束當(dāng)前執(zhí)行并跳出504。這樣的做法好處在于燕侠,不會因?yàn)閭€別慢處理請求導(dǎo)致整站拖垮者祖。當(dāng)然對于有特殊需求長時間處理的業(yè)務(wù)就需要根據(jù)實(shí)際情況來調(diào)整了。由于我們的web系統(tǒng)目標(biāo)是快速且純萃绢彤,那么這樣做很合適我們七问。對于需要長時間執(zhí)行的業(yè)務(wù),我們進(jìn)行了業(yè)務(wù)邏輯拆分使用異步處理的方式進(jìn)行茫舶。
我們系統(tǒng)拆分和分布式系統(tǒng)計(jì)劃還在實(shí)施中械巡,暫且寫到這吧……