/* 記錄兩個(gè)在php7升級(jí)過程中踩的坑。*/
一鸯隅、擴(kuò)展的不兼容
問題現(xiàn)象:
1澜建、升級(jí)完php7的機(jī)器中,有幾臺(tái)從曲線蝌以、指標(biāo)上看炕舵,性能反而不如php5
2、查看其中一臺(tái)跟畅,nginx access日志里大量502錯(cuò)誤
3咽筋、fpm產(chǎn)生大量慢日志,錯(cuò)誤日志里記錄著類似:“WARNING: [pool www] child 31570 exited on signal 11 (SIGSEGV - core dumped) after 490.850482 seconds from start”
初步結(jié)論:
看起來問題是出在fpm徊件,并且間接性core dump了奸攻。遺憾的是,系統(tǒng)配置并沒有保留core文件虱痕。
復(fù)現(xiàn)問題:
1睹耐、聯(lián)系運(yùn)維,摘掉有問題的線上機(jī)流量
2部翘、要一臺(tái)機(jī)器臨時(shí)root權(quán)限硝训,修改機(jī)器配置,以保留core文件
3新思、重啟fpm窖梁,很快就有大量的core文件了。(改回配置夹囚,重啟fpm)
4纵刘、進(jìn)行g(shù)db調(diào)試,如下圖
從調(diào)用棿扌耍可以看到彰导,最后執(zhí)行Memcached::addServers,調(diào)用libmemcached時(shí)出錯(cuò)了敲茄。
可以基本判斷出是使用緩存出問題了。
網(wǎng)上查相關(guān)資料山析,有解釋是這樣說的:memcached長連接的問題 看來似乎還是得從業(yè)務(wù)入手堰燎。
定位問題:
分析nginx access日志,發(fā)現(xiàn)主要集中在兩類請(qǐng)求
1) xxxx/post/detail/?puid=2810963318
2) xxxx/xiaoqu/detail/?xiaoquId=1579&fields=public%2Cstat%2Cfacility
第一類請(qǐng)求正常返回笋轨,第二類請(qǐng)求有很多的502秆剪。配置host在摘掉流量的機(jī)器上調(diào)試赊淑,發(fā)現(xiàn)大量刷頁面時(shí)可以復(fù)現(xiàn)問題。
追蹤代碼仅讽,發(fā)現(xiàn)該業(yè)務(wù)使用了公司的wcache服務(wù)(分布式緩存)陶缺,而wcache使用memcached協(xié)議。將cache注釋洁灵,發(fā)現(xiàn)問題不再復(fù)現(xiàn)饱岸。即可確定是wcache的問題。原因是徽千,service的三臺(tái)機(jī)器wcache客戶端未更新為php7版本苫费,更新后即解決問題。水平有限双抽,未徹底跟進(jìn)舊版本的問題原因百框。
經(jīng)驗(yàn)總結(jié):
1、擴(kuò)展的問題牍汹,一般會(huì)導(dǎo)致fpm出錯(cuò)铐维,甚至導(dǎo)致core。這時(shí)用gdb看一下慎菲,就可以知道是哪個(gè)擴(kuò)展出問題了嫁蛇。網(wǎng)上查查這個(gè)擴(kuò)展相關(guān)的信息
2、從nginx access日志入手钧嘶,則可以知道是哪類業(yè)務(wù)出錯(cuò)多棠众,便于復(fù)現(xiàn)問題,斷點(diǎn)調(diào)試有决。
二闸拿、業(yè)務(wù)的問題
問題現(xiàn)象:
1、升級(jí)完php7的機(jī)器中书幕,有幾臺(tái)從曲線新荤、指標(biāo)上看,提升不大台汇,感覺有異常
2苛骨、nginx access日志里大量499錯(cuò)誤
3、fpm大量慢日志苟呐,錯(cuò)誤日志里記錄著類似:WARNING: [pool www] child 29682 exited on signal 15 (SIGTERM) after 58.730780 seconds from start
初步結(jié)論:
從fpm日志看痒芝,這是php進(jìn)程執(zhí)行過慢,超時(shí)導(dǎo)致fpm進(jìn)程終止牵素。
定位問題:
從nginx access日志里看严衬,499錯(cuò)誤集中在類似:xxx/fang5/2991994508x.htm的請(qǐng)求上,是房源詳情頁的展示笆呆。但是请琳,php5的機(jī)器上access日志有499的錯(cuò)誤粱挡,但是fpm沒有SIGTERM的錯(cuò)誤。
通過打斷點(diǎn)的方式,發(fā)現(xiàn)在詳情頁里,有一處業(yè)務(wù)琴拧,在使用fsocketopen時(shí)寿谴,對(duì)應(yīng)服務(wù)已經(jīng)下線,超時(shí)設(shè)置為800ms,導(dǎo)致一定超時(shí),并且重試1次。
但是灌危,fpm配置里,進(jìn)程超時(shí)時(shí)間設(shè)置為30s碳胳,1.6s也遠(yuǎn)遠(yuǎn)達(dá)不到勇蝙,最多是頁面卡。況且挨约,業(yè)務(wù)代碼在php5和php7是一樣的味混,5下為何沒有問題呢,解釋不通诫惭。
而且翁锡,fsocketopen本身實(shí)現(xiàn)是異步的。
ptrace
修改fpm配置夕土,只啟動(dòng)2個(gè)子進(jìn)程進(jìn)行處理馆衔。ptrace跟蹤任務(wù),看看一次請(qǐng)求php究竟做了些啥怨绣〗抢#狂刷頁面,終于問題復(fù)現(xiàn)了篮撑。
分析日志發(fā)現(xiàn)减细,有大量的socket使用(連接、收發(fā)數(shù)據(jù))赢笨,和nanosleep()系統(tǒng)調(diào)用未蝌。并且nanosleep都是伴隨在socket不可用時(shí)產(chǎn)生的。
這樣就可以分析出茧妒,是底層建立網(wǎng)絡(luò)連接時(shí)萧吠,有很多連接不可用,調(diào)用epoll桐筏,并等待怎憋。最終導(dǎo)致進(jìn)程執(zhí)行時(shí)間過長。這么看來九昧,真的是前面斷點(diǎn)處使用fsocketopen問題咯绊袋?但是30s超時(shí)真解釋不通。
分析ptrace日志铸鹰,發(fā)現(xiàn)socket連接失敗癌别,集中在某幾個(gè)ip和端口。grep業(yè)務(wù)代碼蹋笼,沒找到ip和端口展姐。這時(shí)就需要找運(yùn)維同學(xué)看了。
這些ip和端口對(duì)應(yīng)的服務(wù)剖毯,發(fā)現(xiàn)是session服務(wù)圾笨。
同時(shí),在ptrace日志逊谋,也發(fā)現(xiàn)擂达,確實(shí)寫著mem.ses的字眼。那么基本可以確定胶滋,是session使用出問題了板鬓。把業(yè)務(wù)底層的session使用注釋,發(fā)現(xiàn)問題不再復(fù)現(xiàn)究恤。
問題結(jié)論:
看了一下session的實(shí)現(xiàn)俭令,使用的memcache分布式存儲(chǔ),只在進(jìn)程執(zhí)行結(jié)束時(shí)部宿,釋放session抄腔。那么,當(dāng)大量請(qǐng)求理张、進(jìn)程執(zhí)行慢時(shí)赫蛇,session鎖競爭會(huì)變得非常嚴(yán)重,最終導(dǎo)致php進(jìn)程的超時(shí)涯穷。
解決辦法是棍掐,減少業(yè)務(wù)上的超時(shí)接口,例如前面所述業(yè)務(wù)fsocketopen的1.6s拷况。并建議使用session時(shí)作煌,獲取完數(shù)據(jù)就手動(dòng)釋放,減少鎖赚瘦。
經(jīng)驗(yàn)總結(jié):
配置fpm粟誓,起一兩個(gè)進(jìn)程,用ptrace跟蹤定位問題非常方便起意。