[产品与技术] Flight data recorder

时间:2022-05-06
本文章向大家介绍[产品与技术] Flight data recorder,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

言归正传。

很多人看到这个标题的第一印象可能是 —— 这是要讲飞机上的黑匣子么?有点关系,但主要讲软件中的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提供线索。