導(dǎo)讀 | 作為程序員,相信有一件事是大家最不想見到的。那就是,線上運(yùn)行的系統(tǒng)出現(xiàn)了技術(shù)性故障。(特別還是周末你正在外面happy的時候:D) |
成都創(chuàng)新互聯(lián)主營左權(quán)網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app開發(fā)定制,左權(quán)h5微信小程序定制開發(fā)搭建,左權(quán)網(wǎng)站營銷推廣歡迎左權(quán)等地區(qū)企業(yè)咨詢
處理這類事情特別能體現(xiàn)一個人的綜合能力。因為它會涉及到抗壓能力、對外的溝通能力,以及排查問題所需的技術(shù)能力等等多個方面。如果你還沒機(jī)會成為核心開發(fā),其實很少會有這樣充滿壓力的經(jīng)歷。因為在這個情況下處理事情其實是很慌的,畢竟所有使用系統(tǒng)的人以及他們的老板、你的上級、你的老板等等無數(shù)雙眼睛都在盯著這件事情。
我還記得有一年雙11,我作為“首席問題處理官”正在緊急處理服務(wù)器扛不住壓力的問題,老板默默走到我身后問到“什么問題啊?什么時候好?”。你腦補(bǔ)一下這畫面,想象一下看看。
只要你接下去還會繼續(xù)從事程序員這個職業(yè),我想這樣的場景你總歸會有機(jī)會遇到的。因為一個著名的定律——墨菲定律。墨菲定律:凡是可能出錯的事就一定會出錯。如果沒有一個清晰的應(yīng)對思路,那么一旦發(fā)生線上問題就會像熱鍋上的螞蟻一樣,急得團(tuán)團(tuán)轉(zhuǎn),像無頭蒼蠅一樣到處亂撞(試)。
所以,我這次就想分享一些我多年作為“首席問題處理官”所總結(jié)下來的經(jīng)驗。這可是承載了我N多汗水和腦細(xì)胞的經(jīng)驗~
在日常的項目開發(fā)迭代過程中我們遇到一個bug,大家的處理過程幾乎是一樣的:定位bug -> 解決bug??赡苌俨糠秩嗽诮鉀Qbug之后會有一個思考、復(fù)盤,看看是否有類似bug的地方,一并處理掉。
這個“定位 -> 解決 -> 復(fù)盤”的過程也同樣適用于線上問題的處理。但是必然不僅僅如此。俗話說,解決一個問題最難的地方不是解決的過程,而是定位的過程。所以,針對線上問題我們等不起定位問題所花費(fèi)的時間,因此要將「恢復(fù)」系統(tǒng)正常使用放在最首要的位置。所以,這個過程就變成了:“恢復(fù) -> 定位 -> 解決 -> 復(fù)盤”。
這里多說一句,有一部分人的觀點(diǎn)認(rèn)為,將恢復(fù)系統(tǒng)作為首要目標(biāo),應(yīng)當(dāng)包括犧牲保留現(xiàn)場的動作,因為這個動作可能也需要耗費(fèi)數(shù)分鐘才行。我對這個觀點(diǎn)持反對意見。理由是,解決問題的時長的確是一個很重要的指標(biāo),但是問題既然已經(jīng)發(fā)生,如果由于沒有保留現(xiàn)場導(dǎo)致后續(xù)沒有排查到根源,導(dǎo)致下次該問題再次出現(xiàn),到時候場面將會更加難看。所以我對這事的觀點(diǎn)是,保留現(xiàn)場最重要。因此,這個過程又變成了:“保留現(xiàn)場 -> 恢復(fù) -> 定位 -> 解決 -> 復(fù)盤”。
當(dāng)然了,保留現(xiàn)場也不是說非得面面俱到,花很多時間。用最快的方式保留你當(dāng)下所能想到的所有相關(guān)線索的地方即可。如果事后還是由于線索不足導(dǎo)致未能排查到根本原因,那只能說經(jīng)驗不足,考慮一下以后需要多保留哪些現(xiàn)場數(shù)據(jù)才行。好了,確定了這5個步驟,那么具體每個步驟可以做些什么呢?我來一個個說。
保留現(xiàn)場最最最重要的一件事是保存異常程序的dump文件。有了它,你就可以擺脫盲人摸象式的分析問題,可以快速定位問題的發(fā)源地。
我用了三個“最”來強(qiáng)調(diào)它的重要性。如果你還沒掌握它,那么后面我提到的東西都先放一放,先去掌握它。
另外,如果系統(tǒng)的監(jiān)控體系并不完備的話,還需要將問題發(fā)生時,操作系統(tǒng)、各第三方組件自帶的監(jiān)控數(shù)據(jù)快速地通過截圖保存下來。
保存監(jiān)控數(shù)據(jù)的時候要特別留意一下網(wǎng)絡(luò)相關(guān)的數(shù)據(jù)。如果發(fā)現(xiàn)網(wǎng)絡(luò)相關(guān)的數(shù)據(jù)有異常,那么再把當(dāng)下的網(wǎng)絡(luò)連接情況通過 命令保存下來。因為相對來說,網(wǎng)絡(luò)出現(xiàn)問題的概率遠(yuǎn)遠(yuǎn)大于硬件,不管是程序?qū)е碌倪€是其他原因。規(guī)模越大的系統(tǒng),越是如此。
恢復(fù)系統(tǒng)訪問有很多方法。首先不得不提到一個適用于80%情況的神技了——重啟。沒錯,根據(jù)多年的經(jīng)驗來看這招的確在大多數(shù)情況下很有效。也正因為屢試不爽,所以很多人習(xí)慣性地會在第一時間去重啟,導(dǎo)致現(xiàn)場忘記保存并受到破壞。重啟也分兩種,強(qiáng)制重啟和自然重啟。當(dāng)然優(yōu)先考慮自然重啟,這樣能避免產(chǎn)生一些意料之外的臟數(shù)據(jù)。但是如果是系統(tǒng)出現(xiàn)資源耗用異常的話,就不要傻傻地等自然重啟了,只能強(qiáng)制重啟(kill掉進(jìn)程)。
第二種常見的方法是「回滾」。當(dāng)然它的前提條件是你判斷下來問題的出現(xiàn)是由于最近一次發(fā)布。否則盲目的回滾不但起不到作用,還會越弄越亂,特別在分布式系統(tǒng)中。因為在分布式系統(tǒng)中,一旦上下游耦合的地方出現(xiàn)對接不上,輕則報錯,重則出現(xiàn)大量的異常數(shù)據(jù),夠你后續(xù)折騰好久的。
第三種方法是「降級」。暫停出問題的模塊,停止服務(wù)。當(dāng)然,這個動作需要和業(yè)務(wù)方做好溝通,是否單獨(dú)降級某個模塊會導(dǎo)致業(yè)務(wù)不完整之類的問題。
第四種方法是「限流」或者「擴(kuò)容」。如果你發(fā)現(xiàn)是系統(tǒng)扛不住突增的流量,如果有條件的話可以快速擴(kuò)容幾臺機(jī)器和程序。如果沒法擴(kuò)容的話可以選擇限流,將一定百分比的請求直接拒絕服務(wù)。畢竟所有無法提供服務(wù)和部分無法提供服務(wù)相比,肯定還是后者劃算。
還有一些比較小眾的方法是「切到備機(jī)」、「故障隔離」等,這里就不展開了。它們對環(huán)境、條件的要求更多一些。有時候可能系統(tǒng)并未恢復(fù)到完全正常的狀態(tài),比如,讀取數(shù)據(jù)是OK了,但是某些操作寫入數(shù)據(jù)到時候還是有問題。在這樣的情況下,不要著急定位問題,還是先盡最大努力恢復(fù)到最大程度的可用狀態(tài)再進(jìn)行下一步的動作,畢竟用戶第一嘛。
關(guān)于定位問題,如果有dump文件的話最方便了,通過dump文件分析工具來分析dump文件就可以快速定位到出問題的代碼行,特別是程序阻塞、內(nèi)存溢出、cpu100%之類明顯是程序本身的問題。
不同的語言有不同的dump分析工具,可以自行網(wǎng)上搜一下教程。最終目的就是定位到異常點(diǎn)的堆棧信息,有了它就相當(dāng)于直接把問題代碼出現(xiàn)在哪里都給定位到了。
如果說分析dump文件是跳過抽絲剝繭的步驟,直擊要害的話。通過監(jiān)控數(shù)據(jù)、日志層層分析是個慢活。但是如果缺失dump文件或者從dump文件從未能分析出問題的情況下,也只能選擇后者。
我們在看日志、監(jiān)控數(shù)據(jù)的時候一定要有關(guān)聯(lián)起來看的意識,而不能僅僅在單個維度上看。因為有時候你在單個維度上看到的數(shù)據(jù)像是正常的,但是你關(guān)聯(lián)起來看就不一定了。比如,tcp連接數(shù)降低了一半,但是內(nèi)存反而漲了100%,為什么?這里面可能就藏著故障的線索。
定位到了問題,解決起來就很簡單了。該改代碼的改代碼,該改配置的改配置文件。這里就不多說了,畢竟情況太多,大家遇到的可能都不太一樣。
大家都知道復(fù)盤的好處,但是真正做復(fù)盤的人真不多。如果你不知道從何下手來做復(fù)盤的話,不妨從以下幾個問題入手。
1.這次故障原因是什么?
2.是否有更快的方式在當(dāng)時來恢復(fù)業(yè)務(wù)?
3.如何避免再出類似故障?
4.當(dāng)前系統(tǒng)中是否還有類似的潛在風(fēng)險?
如果你能回答這些問題,我覺得這個復(fù)盤就很到位了,剩下的就是執(zhí)行。
當(dāng)然了,不管如何優(yōu)秀的處理故障,最理想的還是不要發(fā)生故障。所以我們需要在前期做更多的準(zhǔn)備。
我們很多人了解自己負(fù)責(zé)的程序只有通過coding這一種途徑。除非該程序是個單體應(yīng)用,否則這樣的方式是遠(yuǎn)遠(yuǎn)不夠的。
我建議你按照以下清單去了解你的程序:
1.程序包含有哪些模塊,對應(yīng)使用者是哪些?哪些是核心模塊,哪些是可以“棄車保帥”的?
2.多個模塊/系統(tǒng)間如何流轉(zhuǎn)的?(盡量畫一個流程圖,加深記憶)
3.依賴了哪些中間件,誰負(fù)責(zé)維護(hù)他們?
4.依賴了哪些其他的程序,強(qiáng)依賴還是弱依賴,誰負(fù)責(zé)維護(hù)他們?
5.依賴的存儲、消息隊列背后又依賴了哪些存儲,存儲運(yùn)維負(fù)責(zé)人是誰?
6.線上的程序部署在什么環(huán)境。你是否有條件獨(dú)立進(jìn)行部署并調(diào)優(yōu)?
大多數(shù)的故障不是突然發(fā)生,而是有一個逐漸積累的過程,直到爆發(fā)。所以監(jiān)控的價值不僅僅是看看數(shù)據(jù)那么簡單,對于異常識別特別有幫助。
一般監(jiān)控分兩個維度,系統(tǒng)維度和業(yè)務(wù)維度。監(jiān)控指標(biāo)分為三層,「環(huán)境指標(biāo)」、「程序指標(biāo)」、「業(yè)務(wù)指標(biāo)」。具體怎么做我在之前的文章《分布式系統(tǒng)關(guān)注點(diǎn)——360°的全方位監(jiān)控》有具體說明,這里就不贅述了。
如果是分布式系統(tǒng),還可以搭建一個請求鏈路跟蹤系統(tǒng)。有很多成熟的現(xiàn)成解決方案,CAT、SkyWalking、Zipkin、Pinpoint等等。
多說一句,我們在做監(jiān)控預(yù)警的時候,除了設(shè)置閾值還要關(guān)注一下波動率。比如,某項資源日常使用率20%,除了設(shè)置超過80%的閾值進(jìn)行預(yù)警之外,在它產(chǎn)生波動幅度100%(使用率40%)以上的時候也需要預(yù)警,提前讓人關(guān)注。否則一旦以一個較快的速度增長到80%之后,留給你在故障爆發(fā)前消滅它的機(jī)會就非常渺茫了。
另外,針對常見的故障預(yù)設(shè)幾套故障響應(yīng)方案,以及進(jìn)行定期的故障演練(一般上了一定規(guī)模的公司或者處于擴(kuò)張期的公司才會考慮)可以讓團(tuán)隊面對線上故障的時候更加地游刃有余。
假如你不幸成為了線上故障的解決者,如果上級不在旁邊的話,需要定時向上級匯報問題處理情況,以便TA了解問題的嚴(yán)重程度、修復(fù)進(jìn)度并作出決策。
反正就算你不上報,遲早也會被催。與其被動的被催,不如主動上報。
原文來自: https://www.linuxprobe.com/system-down-process.html