很難複製的網路相關問題如何除錯與修正

一個值得大家觀摩學習的除錯過程

最近工作上踩到這個 MaaS 的 bug,這個 bug 結合了號稱是最難除錯的兩個特質 1) 隨機出現、複製率低 2) 網路問題、環境變因多且難以一一固定。不過裡面強者我同事 dann 在 bug 中展示了他如何(快速地) nail down 原因,非常精彩;下面我分別聊聊這整個過程很值得大家觀摩學習的面向。

清楚的解決脈絡

整個過程雖然一開始幾乎沒什麼頭緒,但經過簡單觀察後,就很快地決定採用之前提到的精確具體的假說與實證策略:wget 並不是對同一個目的地每次能有效取得檔案,認為理解這個原因的話就可以找出 bug。

大致上來說整個流程是:
- 建立假設
- 透過試著建立 reproducer 來修正與驗證假設;前後一共試了兩個假設,用三個方式去實驗。
- 假設與對應 fix 驗證後,回報上游做修正

建立 reproducer 的過程比較瑣碎,但也是比較精彩、能夠看出功力的地方,我摘要在下面。

建立 reproducer 的過程

整個過程前後一共試了兩個假設,用三個方式去實驗:

一行程式碼可能需要廣度與深度的知識與技巧

在 dann 除錯的過程中,最後也只是給程式碼的其中一行加上一個選項改寫預設值,就能有效解決問題。這其實是很經典的一個除錯旅程:「累積大量廣度與深度的知識之後,才知道要在最關鍵的地方做改動」。如果觀察很多知名的、大型的開源專案,往往都能看到這種「神奇的一行 fix」。如果只是事後回頭看 commit log,可能不會這個 commit 有什麼值得注意的地方,可說是魔鬼藏在細節當中。

這種「神奇的一行 fix」可能也是讓很多有心的開發者有 impostor syndrome 的原因:「為什麼同行高手都知道要這樣修,是我的話我完全沒頭緒!」,好像是某種「天才才有的靈感」才知道要這樣修正問題。這次有 dann 把整個過程寫下來,其實告訴我們高手也是會假設錯誤、或許高手和我們的差別是高手願意紮實地、系統性地一步一步做分析,並且平時願意在專業上做深度與廣度的累積,才能自在地在系統與高階程式之間轉換 context。

回頭參照 Effective Debugging 一書

如同之前提到的,我們這次也來檢視看看這次整個除錯過程中,有符合哪幾條 Effective Debugging 一書中的建議 (有些只是概念上沾到邊,不一定用了一樣的工具):

順帶一提 Brendan Gregg 的 System Performance

類似於 Effective Debugging 一書,這本也是很不錯;不過我對這本的熟悉度比較低一些,之後也來試著寫點心得。我其實只是想說前陣子的第二版特價有被我搶到。