php一次性能問題優化

php一次性能問題優化

起因

每週五一般都是一個流量相對密集的時刻,所以當流量比以往高的時候,問題就相應出現了。接到報警,系統load值飆高 ,load值200多,cpu使用率100% , cpu sys 70% , cpu sys 30% 。請求耗時描述秒級以上。內存使用正常。cpu使用率,load

在這裏插入圖片描述

在這裏插入圖片描述

快速應急處理

因爲是個週五晚上,都剛到家裏,只能用臨時處理方案,看看能不能快速解決問題。
1. 重啓服務,第一個想到最快的解決辦法,看看重啓是否有效。其結果,cpu和負載下來了。沒過多久,就又回到了起點。cpu load值很快又上去了,所以重啓服務沒有緩解問題。
2. 擴容增配 發現重啓無效之後,因爲這個服務是一個輕量型的一個小微服務,所以當時選擇了個低配的機子,4核8g內存。那最快能緩解的辦法就是擴容增配。因爲我們是雲服務,擴容和增配還是相對簡單快速的。
相比之下,我們先增配,成本最低,來的更快。然後將機器配置升到8核16g,然後作了一次擴容。升配之後是有比較明顯的效果,cpu也下來,不再是100%,load值也下來了,但是cpu使用率也還是不低。因爲升級成8核,所以沒有明顯的處理不過來的現象。

問題排查

等到服務穩定一些,我們要找到問題到底出在哪裏。
一個比較簡單的邏輯操作,爲什麼會有這麼大的耗時,和這麼高的cpu
隨後我就對我們的服務進程進行監控。
看看到底問題到底出在哪裏
首先因爲升配了,看看升配之後我們的服務到底能有多少的qps吧。
壓測的結果很令人揪心啊
在這裏插入圖片描述
結果不堪入目
簡單壓測下來,要分析一下,究竟問題出在了哪裏

strace -c -p 728

在這裏插入圖片描述
發現99%的耗時,系統都消耗在clone上。
clone? 程序中到底幹了什麼,我沒有fork進程啊,爲什麼要clone一個進程出來
那麼看看到底都幹了什麼吧

strace -p 6371

在這裏插入圖片描述

一次請求要作兩次clone,要fork兩個進程出來工作。
然後fork 出來的進程作了一個read 讀了一個ip出來。
經過排查代碼發現,我們代碼中,有一段是要獲取本地ip
用了一個這樣的方法

exec( 「…」 );

執行了一個php 的 exec的操作去拿本地服務ip,這個命令導致了系統會fork進程,去處理exec 執行的外部命令.
所以看進程的strace就能看到 系統內核執行的兩次clone是由於php用了兩次exec導致的。
原因找到了,因爲系統fork進程開銷很大,也很耗時,所以導致我們的服務qps 效率低下,cpu高也是因爲cpu一直在作創建進程,設置進程通信的事。所以,我們就把這兩次exec執行的語句去掉,換了另一種不需要執行exec的操作的方法替換。
再次壓測的結果
在這裏插入圖片描述

效果非常明顯,這樣的結果纔是我們預期的。問題找到了,趕緊修復上線吧,然後觀察一下線上的服務如何。
在這裏插入圖片描述
請求耗時迅速降了一個等級
cpu使用率也立馬見效了。

最後總結一下,線上的服務一定要慎用一些 函數如

exec system passthru

如果需要的話可以試試

pcntl_exec

然後排查問題的時候要找到問題重點再去排查問題; 推薦幾個命令在排查性能問題比較實用,strace , gdb 能幫助你很快找到問題方向,然後再去排查代碼問題。