[產品與技術] Flight data recorder
謝謝這麼多人的關心,程序君現在已經感覺好多了。^_^
有人留言問為什麼不講講OpenSSL的漏洞,一方面我的身份不好講,公司有統一的口徑;另一方面這個話題已經被吵爛了,是個人都在裡面插一腳,程序君就只好退後了。
至於世界邦和途客圈的新聞,請大家不要在公眾號里追問了,我不方便置評,一切以途客圈官方微信和微博的回復為準。
言歸正傳。
很多人看到這個標題的第一印象可能是 —— 這是要講飛機上的黑匣子么?有點關係,但主要講軟體中的flight data recorder。不過我們先從黑匣子講起。
Flight Data Recorder(FDR)用於記錄飛機行駛過程中的各種關鍵數據,其規格如下:
- 電源:115V AC 或 28V DC
- 電源能力:30天不間斷
- 使用期限:至多6年
- 包含水下定位裝置
- 能記錄25小時不間斷數據
- 能經受1100度高溫
FDR的硬體架構:
- CPU card
- Analog card
- Discrete card
- Frequency card
- Audio card
- Power supply card
水下定位裝置能在深達12000ft的水域正常工作,發送37.5khz的聲音信號。
FDR會記錄些什麼?
- time
- pressure
- altitude
- airspeed
- vertical acceleration
- magnetic heading
- control-column position
- rudder-pedal position
- control-wheel position
- horizontal stablizer
- fuel flow
FDR(以及CVR, Cockpit Voice Recorder,記錄機組人員及空乘的對話)對於定位航班失事的原因非常重要,因為它是進行RCA(Root Cause Analysis)的第一手資料。沒有FDR,或者找不到FDR,基本上客機失事就會成為一個永遠的謎團。
下圖展示了FDR在飛機上的位置,以及數據的收集:
而越來越複雜的軟體系統也有這樣的問題。運行在客戶端的軟體,運行的過程中突然崩潰,很多時候單憑崩潰時產生的core很難找到問題的原因(請類比飛機碎片)。這時候,我們就要求助於軟體系統中的FDR了。
最典型,也是最原始的FDR是log。幾乎所有的軟體都有log。通過分析系統崩潰前的log,我們可以找到一些問題的原因,但很多問題依舊無法靠log來進行RCA,這是因為,log的定位是記錄系統的關鍵路徑,關鍵路徑有時候並不一定等同於關鍵數據。
打開debug開關,提供調試版本?很多問題是特定情況的突發事件,需要很隱晦條件才能觸發,debug開關,調試版本這樣的事後諸葛亮,只要問題不能復現,就沒有用武之地。
這就是軟體系統中的黑匣子FDR存在的價值和意義了。
網上關於軟體系統中的FDR的信息還很少,除了我了解的systemtap的flight record mode(FRM)外,就是Java中對FDR的支持了。我們先看Java FDR。
Java FDR是建立在JVM中的,所以只要JVM使能了FDR,所有運行在其上的application都將受益(這又是indirection好處的一大佐證)。它提供幾大功能:
(1) Tracer:tracer捕捉JVM和application中的runtime數據,包括GC,synchronization,compiler (JIT),CPU usage,exceptions,I/O等等信息。
(2) Profiler:定期對系統採樣(追蹤系統的性能),或者on-demand profiling,當且僅當需要時可以打開進行全數據採集(對性能有較大影響,但僅在特定事件下或者特定配置下觸發)。
(3) after-the-fact analysis:即事後分析。捕獲的運行時數據會放在一片循環的緩存中(kernel memory或文件)。當意外事件發生時(比如崩潰),這片緩存中的數據被輸出,用於定位問題。
我對Java和JVM幾乎沒有涉獵,所以以上理解都是皮毛,希望Java大牛來拍磚。
systemtap的飛行模式(FRM)是另外一種FDR。
如果你在linux下進行系統開發而沒有涉獵systemtap,建議研究一下。systemtap給予你寫段腳本runtime注入到目標軟體中,從軟體中獲取信息的能力。這功能如此兇悍,所以你需要"sudo"的許可權來運行systemtap。簡單講一下systemtap的原理:
(1) 首先用戶可以撰寫stap腳本,選擇要注入的進程和函數
(2) stap腳本被編譯成c文件,然後編譯成kernel module,通過insmod載入進內存。
(3) kernel module初始化時會使用do_brk()為目標進程分配新的內存,把要注入的代碼寫入新的內存區域。
(4) 如果要probe的是某條指令,則將該指令替換成跳轉到注入區執行;如果probe的是系統調用,則在系統調用中完成代碼的注入。
(5) 當注入代碼執行完畢後,恢復注入點的代碼,並執行,對於目標進程而言就像正常執行一樣。
下圖是對系統調用 write 進行probe的一個示例:
這個原理和病毒基本一樣。只不過,它的目的是在不用修改目標程序源代碼的情況下,從目標中獲取統計信息,達到runtime debugging / profiling的功效。
如果打開systemtap的飛行模式,則其會不斷往1MB(可配置)的一個Kernel緩衝區中寫監控數據,並且在需要的時候輸出進行分析。
對於FDR而言,有了稱手的工具是遠遠不夠的。最關鍵的是:究竟什麼樣的數據才是關鍵數據,值得記錄,用以崩潰後的分析?如果採樣太多的系統數據,會給系統本身的性能帶來衝擊,而且過多的數據雜音很大,反而不便於分析;如果採樣的數據不夠,無法進行RCA,那麼FDR就失去了應有的作用。
此外,對數據合理的visualization也非常重要,因為它能幫助人更好地理解數據間的關係,從而為RCA提供線索。
如果你對本文感興趣,歡迎訂閱公眾號『程序人生』(搜索微信號 programmer_life)。每天一篇原汁原味的文章,早8點與您相會。
推薦閱讀:
※[雜談] 當你回首往事的時候
※軟體性能調優:看數據,還是看概念?
※為什麼這麼多人把「Wikipedia」稱作「wiki」?
※等待還是放下?
TAG: | 迷思 |