你所需要掌握的問題排查知識
1. 說之前
由于業(yè)務應用 bug(本身或引入第三方庫)、環(huán)境原因、硬件問題等原因,線上服務出現(xiàn)故障 / 問題幾乎不可避免。例如,常見的現(xiàn)象包括請求超時、用戶明顯感受到系統(tǒng)發(fā)生卡頓等等。
作為一個合格的研發(fā)人員(技術人員),不僅要能寫得一手好代碼,掌握如何排查問題技巧也是研發(fā)人進階必須掌握的實戰(zhàn)技能。這里提到的排查問題不僅僅是在Coding的過程中Debug,還包括測試階段、線上發(fā)布階段問題的排查。特別是在生產環(huán)境中,一般是沒辦法或很難進行Debug操作的。 而通過掌握服務線上問題排查思路并能夠熟練排查問題常用工具 / 命令 / 平臺來獲取運行時的具體情況,這些運行時信息包括但不限于運行日志、異常堆棧、堆使用情況、GC情況、JVM參數(shù)情況、線程情況等。
排查出問題并找到根本原因加以解決,其實是一件很成就感的事情。曾經有人問過我:“你是怎么想到問題出現(xiàn)在xxx的?又是怎么確認根本原因是xxx的?”,我只能輕描淡寫的回答:“靠經驗”,其實這里說的“靠經驗”是很模糊的,一直以來大家可能都覺得排查問題要靠經驗,但是又說不出具體通過什么樣的經驗排查出了問題。而本質上排查定位線上問題是具有一定技巧或者說是經驗規(guī)律的,排查者如果對業(yè)務系統(tǒng)了解得越深入,那么相對來說定位也會容易一些。排查問題的關鍵是什么?一句話總結:給一個系統(tǒng)定位排查問題的時候,知識、經驗是關鍵,數(shù)據(jù)是依據(jù),工具是運用知識處理數(shù)據(jù)的手段!在此,我將結合自身經歷、總結,說關于“問題排查”的方法論,希望能與您產生更多的共鳴。
注:由于針對不同技術問題,所用到的排查工具,命令千差萬別,所以本文將只介紹思路,不涉及具體排查命令的介紹。
2. 有哪些常見問題
那我們經常說遇到這樣那樣的問題,那到底有哪些問題,問題又集中在哪些方面?對于不同技術框架、語言族所可能引發(fā)的問題也會存在很大的差異,但基本的套路排查思路都還是一致的,以Java為例。
所有 Java 服務的線上問題從系統(tǒng)表象來看歸結起來總共有四方面:CPU、內存、磁盤、網絡。例如 CPU 使用率峰值突然飚高、內存溢出 (泄露)、磁盤滿了、網絡流量異常、FullGC 等等問題。
基于這些現(xiàn)象我們可以將線上問題分成兩大類: 系統(tǒng)異常、業(yè)務服務異常。
1. 系統(tǒng)異常
常見的系統(tǒng)異常現(xiàn)象包括: CPU 占用率過高、CPU 上下文切換頻率次數(shù)較高、磁盤滿了、磁盤 I/O 過于頻繁、網絡流量異常 (連接數(shù)過多)、系統(tǒng)可用內存長期處于較低值 (導致 oom killer) 等等。
這些問題如果是在Linux系統(tǒng)下可以通過 top(cpu)、free(內存)、df(磁盤)、dstat(網絡流量)、pstack、vmstat、strace(底層系統(tǒng)調用) 等工具獲取系統(tǒng)異常現(xiàn)象數(shù)據(jù)。
注:CPU 是系統(tǒng)重要的監(jiān)控指標,能夠分析系統(tǒng)的整體運行狀況。對CPU的分析或監(jiān)控指標,一般包括運行隊列、CPU 使用率和上下文切換等,內存是排查線上問題的重要參考依據(jù),內存問題很多時候是引起 CPU 使用率較高的主要因素。
而經常遇到內存占用飆高它的原因可能有很多。最常見的就是內存泄露。可以得到堆dump文件后,進行對象分析。如果有大量對象在持續(xù)被引用,并沒有被釋放掉,那就產生了內存泄露,就要結合代碼,把不用的對象釋放掉。
2. 業(yè)務服務異常
常見的業(yè)務服務異常現(xiàn)象包括: PV 量過高、服務調用耗時異常、線程死鎖、多線程并發(fā)問題、頻繁進行 Full GC、異常安全攻擊掃描等。
頻繁的 GC 將導致應用吞吐量下降、響應時間增加,甚至導致服務不可用。
3.問題排查方法論
一、排查問題猶如破案
排查線上問題猶如警察破案一樣,是一個不停分析線索,推理的過程,但在準備排查問題之前,我們應該明白三個認知:
- 系統(tǒng)出現(xiàn)異常是正常的
時至今日計算機系統(tǒng)已經變得異常復雜,一次用戶請求可能要經過發(fā)送請求,DNS解析,運營商網絡,負載均衡,服務器,虛擬機(容器),視業(yè)務邏輯的復雜程度可能還要調用組件,緩存,存儲和數(shù)據(jù)庫等。每個環(huán)節(jié)都可能出現(xiàn)問題,有的組件又是分布式的,大大增加的排查問題的難度,所以出現(xiàn)問題后不要慌,保持好的心態(tài)。
- 首要任務是恢復系統(tǒng)
飛機在發(fā)生緊急情況下,飛行員的首要任務是保持飛機飛行,相比保證乘客與飛機安全著陸,故障定位和排除是次要目標”,所以恢復線上系統(tǒng)是首要任務,而不是立馬找到它發(fā)生的原因。
- 真相永遠只有一個
計算機是一門科學,而且計算機的世界里都是由0或1組成,在這個世界里只有是或否,沒有中間地帶,所以在計算機世界凡事都有根本原因,沒有偶然發(fā)生,一切都是必然。正如墨菲定律所提到的“如果事情有變壞的可能,不管這種可能性有多小,它總會發(fā)生!”
二、了解案情,評估大小
先評估出這個問題的影響范圍,是全網,某些地區(qū),還是某條鏈路不可用的問題,還是很多業(yè)務線都出現(xiàn)問題,評估出案情的大小,到底是普通的民事案件,還是刑事案件。
三、理清線索,整理分析
理清手頭已得到的信息或線索,比如監(jiān)控上有網絡報警,有用戶反饋無法訪問,有開發(fā)人員反饋服務器有問題,同時間段有做變更等等,盡量不要漏掉這些看似無關緊要的線索,把這些線索先整理下來,后面一并分析。
推理的過程,就是根據(jù)已知線索,通過合理的想象、推斷得出一個唯一的結果。線索是整個推理過程的起點,線索給出的好有不好、是否有錯誤,直接會影響推理的質量,因此是最基礎、也是最重要的一環(huán)。線索的梳理,最常犯錯誤就是信息不足,主觀臆斷。
其中整理分析過程中,很重要的一點:盡可能搞清楚問題的前因后果!
不要一下子就扎到服務器前面,你需要先搞明白對這臺服務器有多少已知的情況,還有故障的具體情況。不然你很可能就是在無的放矢。
必須搞清楚的問題有:
-
故障的表現(xiàn)是什么?無響應?報錯?
-
故障是什么時候發(fā)現(xiàn)的?
-
故障是否可重現(xiàn)?
-
有沒有出現(xiàn)的規(guī)律(比如每小時出現(xiàn)一次)
-
最后一次對整個平臺進行更新的內容是什么(代碼、服務器等)?
-
故障影響的特定用戶群是什么樣的(已登錄的, 退出的, 某個地域的…)?
-
基礎架構(物理的、邏輯的)的文檔是否能找到?
-
是否有監(jiān)控平臺可用? (比如Munin、Zabbix、 Nagios、 New Relic… 什么都可以)
-
是否有日志可以查看?. (比如Loggly、Airbrake、 Graylog…)
另外也可以進一步從應用層、數(shù)據(jù)庫層、網絡層進行檢查:
應用層:
-
應用最近是否有上線?
-
軟硬件環(huán)境最近是否有變更?
-
應用日志是否有異常?
-
重啟是否有效?
數(shù)據(jù)庫:
-
數(shù)據(jù)庫系統(tǒng)級配置最近是否有變更?
-
telnet端口是否暢通?
-
tnsping監(jiān)聽是否正常(連通性、延遲)
-
數(shù)據(jù)庫是否有異常的等待?
-
遠程、本地SQL執(zhí)行是否正常?
網絡:
-
網絡最近是否有變更?
-
ping是否正常?
-
traceroute -l 是否正常?
-
網絡是否有丟包、延遲?
盡可能地獲取到更多的已知有效信息,匯總信息并從多條排查線去進行分析,這里推薦思路有:
-
通過變更記錄來咨詢相關人員,大量問題其實都是上線、變更等引起的,所以排查下同時期有過業(yè)務相關的變更操作人員,往往就可以把很多問題排除在這道線上了。
-
通過日志、數(shù)據(jù)等,把一些已知問題篩選出來。
-
通過影響人群、問題點等信息嘗試找出復現(xiàn)方法。一般來說,能有方法穩(wěn)定復現(xiàn)的問題,就比較容易排查到了。
-
到這一步的問題,基本上都屬于一些疑難雜癥了,就沒有一些特別通用的方法了。需要開闊思路,找找規(guī)律,將平時沒關注到的技術、業(yè)務點再了解的更細致,更深入一些,或者求助于團隊的幫助一起來解決。
需要注意一點:通過分析日志時,業(yè)務日志除了要關注系統(tǒng)異常與業(yè)務異常之外,還要關注服務執(zhí)行耗時情況,耗時過長的服務調用如果沒有熔斷等機制,很容易導致應用性能下降或服務不可用,服務不可用很容易導致雪崩。如果沒辦法直接從日志中發(fā)現(xiàn)異常,那就只能看看應用到底在干嘛了(可分析應用在異常時期的線程內存堆棧信息)。
這一步原則很簡單:找出系統(tǒng)正在執(zhí)行“什么”,詢問系統(tǒng)“為什么”執(zhí)行這些操作,以及系統(tǒng)的資源都被用在了“哪里”可以幫助你了解系統(tǒng)為什么出錯。
四、擴大你的信息量
主動擴大信息的接收面,比如問詢一下開發(fā)或其它相關同學,今天有沒有做線上改動,網絡組有無重大調整。從中獲取到有價值的信息點,對于排查問題至關重要。查看監(jiān)控,細看某個監(jiān)控項的變化,追蹤日志和調試信息都是擴大信息量的手段。
拓展知識面,閑暇時間多些了解相關聯(lián)系統(tǒng),比如架構,部署,邏輯等。一旦故障發(fā)生,討論中也可提供你解決辦法的思路,舉一反三,推進問題的排查與解決。
收集問題及環(huán)境信息,需要收集的信息可能有:
-
問題的已知首次發(fā)生時間
-
問題反饋人員所處的環(huán)境,例如省、市、ip、ISP、瀏覽器、手機型號、app 版本等
-
問題是全員的還是部分的。
-
問題發(fā)生在哪些服務器上。
-
同期相關的日志、數(shù)據(jù)信息。
-
同時期的上線、配置變更、運維操作、基礎服務變更等記錄。
-
同時期基礎服務提供商的變更、故障公告等。
五、分析證詞,甄別對錯
如果是外部提出的問題,比如業(yè)務投訴,用戶反饋等信息,有時候是可信的,有時候人卻是不可信的,舉個例子之前有開發(fā)反饋效果有問題,有些廣告位bias異常,有些正常,讓我們幫查查系統(tǒng)的問題,但是最后是代碼調用一處動態(tài)配置造成的。有些時候反饋的信息,是經過描述者過濾加工過的信息,他的排查和分析有可能把你帶偏了,在收集信息同時需要以審視、懷疑的態(tài)度,分析每個人的證詞。
六、看清問題本質
“當你聽到蹄子聲響時,應該先想到馬,而不是斑馬”,看到一件現(xiàn)象或一件事情,要看實質而不只是表面的東西,聽到馬蹄聲時候猜是什么馬,是什么人的馬,是來干什么的而不是猜它是斑馬還是白馬還是黑馬。排查問題也一樣切忌先入為主,有時候你覺得極其簡單,看似非常不可能發(fā)生的事情,可能就是原因,不要輕易的排除掉某項原因。例比:之前遇到有個mysql連接異常的問題,查了很久,做了很多調優(yōu)都沒有解決,最后發(fā)現(xiàn)是網卡跑滿了。
七、確定方向,開展定位
排查步驟,可以先“從大到小”,先看比如運營商網絡,機房狀態(tài)等比較宏觀的地方是否有問題,逐一排除,逐步縮小問題范圍。再“從上到下”,先從現(xiàn)象發(fā)生的頂端調用鏈逐一排查,逐步向下深入。
但也并不是所有問題都從大到小從上到下,宏觀問題只有達到一定量級才會引發(fā)”質變”,從而引起的注意,在通往質變過程中,你的業(yè)務可能已經收到某中影響而表現(xiàn)的很明確,此時需要微觀分析,然后再逐漸到宏觀來診斷。
八、卷宗記錄,破案歸檔
問題排查解決后,養(yǎng)成事后總結的習慣。好記性不如爛筆頭,然而在一片混亂問題分析當中,心平氣和地記錄下問題與判斷確實有點不切實際。但即使如此,我們仍然可以在事情結束后為保留一份分析資料,總結并記錄處理過程中的執(zhí)行步驟以及解決途徑,則能幫助自己和團隊積累寶貴的處理經驗。
- 對于個人
一次問題的定位解決往往伴隨著個人的成長,我們不要放棄這樣的機會。在追查過程中了解的知識點是比較零碎的,不系統(tǒng)。事后就需要大家將這些點整體串起來,并且以點帶面,將知識點變更知識面。
- 對于團隊
-
是對這次問題的反思,我們應該在流程、代碼、工具或者哪些方面做出調整,可以更好的避免同類型問題的出現(xiàn)。
-
是對追查過程的總結,在問題定位的過程中,我們缺少哪些幫助及工具的支持,能否更好的提升排查問題的效率,然后相關人員是否對過程結果存在異議。
4. 長期改進建議
吃一塹長一智出了問題并不可怕,怕的是我們從問題中學不到什么,怕的是類似的問題重現(xiàn),提高問題定位的效率,有哪些值得去做,比如:
1、建立長效錯誤碼機制,使用具統(tǒng)計、可視意義的數(shù)字來簡短描述錯誤含義和范疇,正所謂濃縮就是精華,這一點在錯誤碼屢試不爽。
2、正常程序中打錯誤日志主要是為了更好地排查問題和解決問題,提供重要線索和指導。但是在實際中打的錯誤日志內容和格式變化多樣,錯誤提示上可能殘缺不全、沒有相關背景、不明其義,使得排查解決問題成為非常不方便或者耗時的操作。而實際上只要開發(fā)稍加用心,也需就會減少排查問題的很多無用功。如何編寫有效的錯誤日志,建立日志標準,也是非常有利于問題分析的。
3、定位問題避免二次損害,當某個看似難以捉摸的難題出現(xiàn)時,本能可能是重啟,盡快讓系統(tǒng)恢復正常。雖然這樣的方式經常能夠解決問題而且起效神速,但同時也很可能把情況推向令人難以置信的惡化深淵。問題排查手段包括重新啟動不穩(wěn)定系統(tǒng)、嘗試自動記錄數(shù)據(jù)庫、文件系統(tǒng)修復等等,這些方式往往確實能搞定難題并讓系統(tǒng)重回生產軌道,但同時也沒準導致數(shù)據(jù)恢復努力付之東流,毀掉確定問題根本原因的機會甚至大大延長關鍵性系統(tǒng)的停機時間。保留現(xiàn)場也非常重要,跟破案現(xiàn)場要要求現(xiàn)場勘察、樣本采集、排查、鎖定如出一轍,對于難以重現(xiàn)問題,盡量創(chuàng)造條件保留了可以用于故障重現(xiàn)的數(shù)據(jù)或現(xiàn)場。線上環(huán)境復雜多變,雖然這一點并不能馬上解決問題起到直接作用,但堅持這種處理思路,為開發(fā)和測試創(chuàng)造條件,降低因難以重現(xiàn)的疑難故障的掛起率,最終有助于業(yè)務的長期穩(wěn)定。
4、建立集中的數(shù)據(jù)可視平臺,不至于遇到問題才開始著手分析,若是對業(yè)務沒有足夠的了解又沒有數(shù)據(jù)依賴,就很可能在解決問題時雪上加霜。
5、建立沙箱影子系統(tǒng),模擬復雜多變的現(xiàn)網環(huán)境,規(guī)避線上影響,重現(xiàn)或壓測問題,如tcpcopy、dubbocopy等。
6、搭建開源的日志可視方案,協(xié)助我們去解決最后”一公里”的問題,常見如ELK、Log.io等。
7、善其事必先利其器,常見系統(tǒng)排查工具perf、iptraf、netperf、tcpdump、gdb、pstack、jstack、strace,top、iotop、tsar等。
8、在升級版本或者替換或修改文件時,一定要做好備份,要保證隨時可以還原。
9、程序在使用多線程時,盡可能的減少多線程競爭鎖,可以將數(shù)據(jù)分段,各個線程分別讀取。
10、盡量不要在線程中做大量耗時的網絡操作,如查詢數(shù)據(jù)庫(可以的話在一開始就將數(shù)據(jù)從從 DB 中查出準備好)。
11、建議對線程取一個有意義的名稱,這樣對于在排查問題時很有必要,如當拿到程序線程堆棧信息時,可直接根據(jù)線程名在日志中找到相關的堆棧。
12、生產環(huán)境進行問題排查時一定要保證不要影響正常的業(yè)務執(zhí)行。
原文鏈接:技術大全-公眾號:mikezhou_talk【你所需要掌握的問題排查知識】

浙公網安備 33010602011771號