今天雙十一,木有節目!!!靜靜寫個文章吧 :-D
2018 年元旦前夕,公司業務系統流量突然增加 5~6 倍,然而並無相關預演或準備,於是乎系統癱瘓了,錢也不再進賬了,對於小公司來說,痛並快樂著!
經過此次撲火搶救,個人總結了一些小經驗,大廠用不上,但對總共就幾個人的小微公司而言可能有些幫助。
PHP 技術棧,然而道理是相通的!不必糾結世界上最好的語言是哪個 :)
簡略版
- 升級至 PHP7
- 啟用 OPcache
- 借日誌識別隱患和瓶頸
- 清理資料庫慢查詢
- 關閉 Debug 及 Log
增加快取時間
補充版
- 還沒升級到 PHP7 的,如果可以,建議升級。個人認為,無關效能,這一種擁抱變化、敢於挑戰的追求,萬年 CentOS 6.x 甚至 5.x 式的穩定就小公司而言不太好。小公司的穩定應該是花最少的錢,做最多的事,讓產品迅速上線、高效運轉,源源不斷的正向現金流。技術債必須欠,但不應該欠太多啊!簡單地說,產品技術棧不願升級的壞處就是無法充分享受開源的好處,造輪子並非小公司的強項,當然如果是錢多得沒地花的話就忽略我吧。
並非有意針對CentOS。不過本科的時候折騰過CentOS、Fedora、openSUSE、Mandriva Linux、Elementary OS、Debian、Ubuntu, Ultimate Edition、紅旗 Linux、Ylmf OS(雨林木風OS,並非Ghost版啊,哈哈哈。現名StartOS)、Linux Deepin(深度OS,同樣並非Ghost版!)……各種我能接觸到的 Linux 發行版,最終還是認為 Ubuntu 更友好,適合我這樣的小白使用者,畢業後遇到了 Linux Mint,至今已用 5 年+。最開始做 iOS 開發的時候還用的虛擬機器(當時我的筆記本 i7+16G+SSD,虛擬機器還行),後來同事離職騰出一臺 MBP,用了一年左右吧,再後來就不用了,一方面是不再從事 iOS 開發,另一方面是我省吃儉用換了一臺 i7+GTX1070+64G+SSD+4K螢幕的筆記本(第一件事情依然是格盤裝上 Linux Mint)。。。
-
啟用 OPcache,鳥哥部落格文章 《讓PHP7達到最高效能的幾個Tips》 第一條。
-
日誌建議重點關注兩點:
- php-fpm 的 slow log (如程式碼中是否出現 sleep 一類的函式?實在有必要嗎?)
- 資料庫的慢查詢日誌 (索引、觸發器、儲存過程等可能造成慢查詢甚至鎖表)
-
清理資料庫慢查詢
個人認為,就一般網際網路小公司而言,系統瓶頸一般先出現在資料庫。可能平時業務量小,硬體資源充足,問題不顯現,估計都不太重視這問題。資料庫連線池的問題並不是瓶頸,面對大量的慢查詢再多的連線池也不管用啊,先把慢查詢處掉就好了,查詢慢甚至鎖表可能只是個索引的問題。。。
- 關閉 Debug 這個沒啥好說的,但就怕忘記了!!!至於 Log 嘛,看情況吧,要注意非非同步的、可能引起阻塞的 Log (比如說直接在每一個 request 裡同步寫日誌就不合適)
太長不看版 (覆盤)
2018 年元旦前夕,系統流量瞬間猛增 5~6 倍,可近期並無廣告推廣投入啊,當時第一反應是遭到攻擊了,但冷靜一想,哪個閒著沒事盯上個小公司,多大仇啊。檢視各種資料推斷此次為自然流量。
由於無相關演練和應急預案,系統癱瘓了,公司收入也基本停了,痛並快樂著!
我當時首先建議升級 PHP。將其中一臺伺服器升級後發現記憶體和CPU消耗減半 (注:其實並未真正解決問題)。
接著其它伺服器也升級了,可尷尬的是,沒過多就,系統又癱瘓了,而且多了很多錯誤日誌。我司用的PHP框架是 ThinkPHP 3.x,疊加歷史遺留問題,根本不可能平滑升級。於是乎降級回到 5.6 的版本。
回到原點,而且問題沒有解決!!!
於是乎,下一個嘗試是,增加伺服器數量、提高資料庫連線數上限(阿里雲的資料庫)。然而都加倍了,壓力還是沒有緩解!沒有緩解!換句話說,關鍵不在此,再加就是花冤枉錢。
接著我拿到了一臺伺服器的 SSH 賬戶。
注:我個人負責的工作相對雜亂,從 Android 到 iOS,到 Java web 再到 PHP web……,但卻沒管過公司伺服器的維護工作,當然我個人負責的外包專案的話就是從伺服器選購、系統環境配置到專案開發、部署、維護……,從 0 到 1 全包了。
我首先啟用Opcache,然後調整了 nginx 和 php-fpm 的一些引數,起到了一定的作用,但並未解決問題。
然後我順手把 PHP 的慢執行日誌 slow log 開啟了。由於系統堵得厲害,一大堆的 log,沒能抓到關鍵,當天無果。
推薦個好用的工具 mosh,關鍵時候不掉線哦
畢竟使用者也是要休息的,慢慢流量下去了,系統恢復正常。不過晚上也沒夢到解決方案 :-D
第二天,繼續排查,各種調參無果。中午吃過飯後,媽給我來了個電話,問我是不是在加班。這。。。
掛電話後,我犀利的眼睛注意到了一條不起眼的日誌,順著日誌指示的行數,我翻看了一下程式碼,發現該行呼叫了個 usleep 函式,5 秒鐘,我的天,沒必要吧,於是乎我直接把它註釋掉,重啟 php-fpm,奇蹟出現了,該臺伺服器瞬間暢通!接著排查了所有程式碼中出現的 usleep 函式,統統註釋掉,重啟 php-fpm。
系統恢復正常服務,錢也開始進來了。。。
然而故事到了這裡還沒結束!
下午流量又逐漸增加,到傍晚飯點的時候,系統又響應緩慢了,但當時我在外吃飯,沒帶電腦,一時也趕不回去,沒辦法,我只好掏出手機試試了。還好下午有先見之明,準備了個批量重啟伺服器 php-fpm 的工具,一重啟它就恢復正常了,過段時間堵了就再重啟,本來是有效的,可流量還在增加,慢慢地就不管用了,不過這時我已經吃完飯回到家。馬上電腦開啟,繼續奮戰!
再推薦個小工具 PSSH (Parallel SSH)
最後同事定位到的原因是,另一個子系統的資料庫的 session 資料表沒新增索引,導致 session 過期的時批量刪除的時間過長,估計是鎖表了。
主系統還可能出問題的地方我都檢查過了(其實我是不清楚還有個老系統在跑☺),而且 session 的驅動也從 mysql 換到了 redis,沒想到的是拖後腿的是個子系統,一款已上線多年的App (此次流量全是它引來的),把資料庫拖垮了。
session 表新增索引後,系統又恢復正常了。
回顧整個撲火過程,關鍵點有兩個,一是 usleep 函式,二是資料庫索引,啟用 OPcache 是有些作用的,而關閉資料庫觸發器啥的也起到了不小的作用,而增加介面快取時間的操作其實治標不治本,沒有從根本上解決問題,而且這次連表面上解決問題的作用也沒起到。
此次撲救的突破口在於日誌,一是 php-fpm 的慢執行日誌,二是 mysql 的慢查詢日誌。通過排查導致 php-fpm 程式排長隊的原因就能順藤摸瓜解決問題。
在伺服器資源一定的情況下,php-fpm 的程式數同樣有限,如果出現程式休眠(例如 usleep )或資料庫連線數達上限(慢查詢導致)的話,伺服器資源充足的情況下沒問題,但 php-fpm 的程式一旦排長隊,接下來很可能就是雪崩效應,系統就癱瘓了。
以上是本人的一點經驗總結,可能存在不少錯誤和不足,歡迎各位小夥伴來指正和討論,謝謝!
本人普通 985 工科院校,工商管理類專業,雙學位。創業小公司工作 5 年+,全包工程師,
因離家太遠,近期在尋求珠三角地區的新坑,偏後端方向,求介紹啊(已換坑)!