標籤:

[產品與技術] 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: | 迷思 |