什么是專家?專家不是說只知道系統如何工作的,而是通過調查系統為什么不工作,積累經驗成長成專家的。——Brian Redman
事情正常運作是事情出錯的一個特例。——John Allspaw
我們認為問題解決是可以學習和可以指導的。問題解決依靠兩點∶問題解決的邏輯和系統知識。
理論:
在理想模型中(如下圖所示),我們通過問題報告來了解系統出了什么問題。然后我們去看系統現象和日志來了解目前系統的狀態。這信息和我們知道的系統設計,工作原理,失效模型結合起來,使我們定位出一些可能導致系統失效的原因。
通常有兩個方法來驗證我們的假設。我們可以對比系統的狀態和我們的理論來找到確認或不確認的證據。或者,在某些情況下,我們可以在受控的條件下去改變系統,觀察結果。選用其中一個方法,重復測試直至找到根因,然后再采取正確的措施來規避問題再現,同時寫個事后報告。當然,解決可能的問題不一定非要等找到根因之后再處理。
常見陷阱:
1.查看不相關的問題或對系統矩陣的錯誤理解。
2.為了安全和有效的驗證假設,錯誤理解如何改變系統參數、環境。
3.有關錯誤想到的是不大真實的理論,或關注于過去問題的原因上,認為既然它發生過,它肯定會再次發生。
4.找到假的相關性,這些相關性實際是起因的巧合或相關內容。
不要想復雜了,考慮事情更有可能發生的情形。醫生常常被教導:當你聽到蹄聲,想想有可能不是斑馬。
我們知道什么,不知道什么,應該知道什么的方法論。
實踐:
事實上,問題解決永遠不會和我們理想模型一樣簡明。我們可以采取一些步驟使得我們的過程更加簡潔和高效。
一、問題報告
所有的問題都源自于問題報告,有效的報告應該包括期望的動作,實際的動作,最好包括這個實際的動作是如何產生的。理想的情況下,這些報告應該有一個固定的格式和方便查詢到的存儲的地方。我們的團隊經常用定制化的格式和小的web應用來查詢相關的問題信息。這也為故障自查和自愈系統提供了工具。
在谷歌針對每一個問題開一個bug是很常見的做法。我們的隊伍不鼓勵報告直接發給某個人,理由如下:這個做法導致了多加一個將報告轉化為bug的過程,產出的低質量報告對團隊其他成因不可見。發給團隊的話可將問題解決的壓力集中到多人的身上。
二、問題分類
當你收到一個問題報告,下一步是明確將怎么做。比如根據事情的嚴重性來確定處理優先級。你的第一直覺不應該是找到根因,而是盡快恢復系統。就像飛行員一樣,問題查找是第二要素,第一是確保乘客安全著陸。
三、問題檢查
我們應該要做到知道系統中的任何一個部件是做什么的,這樣才能明白它是否正常工作。
理想情況下,監控系統會為你的系統記錄矩陣,可以通過矩陣來定位問題。圖表-時間和操作-時間是個有效理解系統行為的方法。
日志記錄也是一個很有價值的工具。系統狀態的日志記錄會告訴你系統某個時間點在干什么?你需要分析一個或幾個系統的日志。可以通過使用Dapper工具來跟蹤需求是個理解一個分布式系統如何工作的方法。
展示目前狀態是第三個工具。Google的服務器通過終點來展示系統是否正常。這些終點可以讓你不需要架構圖就可以了解任何系統和其它系統的交互情況,也可以展示錯誤率和延遲的直方圖。
最后,你需要指導一個客戶來做實驗,來發現這些需求返回的是什么狀態。
第四、問題診斷
全面理解系統設計有助于提出系統可能出現問題的假設,一些遺傳的實踐也可以在沒有主要知識的情況下幫助問題診斷。
1. 簡化和減少
理想情況下,系統會有明確定義的界面以及輸入輸出的轉化過程。然后可以通過部件間的聯系(如數據流)來確定給定的部件是否正常。通過給定的測試數據輸入,來檢查輸出結果。有一個固定的可再生的測試案例可以使debug更快一些,這些測試案例也可以在有攻擊性的或風險高的技術要求的非生產環境使用。
劃分和解決問題是非常有用的問題解決方案思路。和數據流的處理方式類似,也是看系統端到端是否出現問題。在一個非常大的系統中,線性處理問題可能會比較慢,所以將系統劃分成兩部分進行診斷很有必要。找到哪部分出了問題之后,再通過二分法進行處理直到找出錯誤的部件。
2. 多問"what" "where""why"
一個故障的系統通常仍然會嘗試做一些事情,一些你不想讓它做的事情。找到它在做什么,然后問為什么它這樣做?它的輸入和輸出是什么?有助于你了解為什會出現問題。
3. 最終觸發的條件
系統是有規則的,最近系統的變更最有可能導致問題出現。
4. 特殊的診斷
在很多領域,之前介紹的工具對問題診斷是非常有幫助的。Google SRE花很多時間在工具建設上。很多工具僅對給定的系統有幫助。確保找到服務和團隊之間的公用之處,避免重復浪費時間和精力。
第五、測試和對癥下藥
一旦你找到了可能問題原因的清單,就可以開始去查找問題的根因了。在設計測試方案時,要考慮如下幾點:
1. 理想的測試有多個選擇項,這樣可以管理一組假設,但實際上這個很難達到。
2. 先考慮顯而易見的問題。比如先減少需要來測試,考慮測試帶來的風險,在處理網絡連接性問題前找兩臺機器測試下。
3. 測試可能導致誤解性的結果。
4.考慮測試本身帶來的影響,如CPU,性能問題等。
5. 測試結果是建議性的,而非直接結果。
要清晰記錄你的思路,以便于測試你的想法是否正確。
第六、問題解決
你已經將多個可能的問題原因減少到一個了。下一步就是要證明這就是實際的根因。常見的方法是讓問題再現,但這個在生產環境很難實現。原因主要有兩個:一是系統比較復雜,可能單個問題都不是問題,但所有的問題集中起來就會導致問題發生;二是若在生產環境再現這個問題會導致影響SLA,這個是不能被接受的。
一旦問題發生,要寫故障報告。
如何讓問題處理更簡單:利用白盒矩陣和結構化日志建設可觀察性;設計系統結構間易于理解的和可觀察的交互界面。
注:
否定的結果也很神奇。否定是指實驗結果沒有和計劃的保持一致。否定的結果對其他人也是有幫助的,發表使你驚訝的結果吧,這樣其他人包括你自己才不會驚訝。