动态追踪技术 Dynamic Tracing
https://openresty.org/posts/dynamic-tracing/
工欲性能调优,必先利其器(2)- 火焰图| PingCAP https://pingcap.com/blog-cn/tangliu-tool-2/
什么是动态追踪
我很高兴能在这里和大家分享动态追踪技术(Dynamic Tracing)这个主题,对我个人来说也是一个很激动人心的话题。那么,什么是动态追踪技术呢?
动态追踪技术其实是一种后现代的高级调试技术。它可以帮助软件工程师以非常低的成本,在非常短的时间内,回答一些很难的关于软件系统方面的问题,从而更快速地排查和解决问题。它兴起和繁荣的一个大背景是,我们正处在一个快速增长的互联网时代,作为工程师,面临着两大方面的挑战:一是规模,不管是用户规模还是机房的规模、机器的数量都处于快速增长的时代。第二方面的挑战就是复杂度。我们的业务逻辑越来越复杂,我们运行的软件系统也变得越来越复杂,我们知道它会分成很多很多层次,包括操作系统内核然后上面是各种系统软件,像数据库和 Web 服务器,再往上有脚本语言或者其他高级语言的虚拟机、解释器及即时(JIT)编译器,顶上则是应用层面的各种业务逻辑的抽象层次和很多复杂的代码逻辑。
这些巨大的挑战带来的最严重的后果就是,今天的软件工程师正在迅速地丧失对整个生产系统的洞察力和掌控力。在如此复杂和庞大的系统中,各种问题发生的概率大大提高了。有的问题可能是致命的,比如 500 错误页,还有内存泄漏,再比如说返回错误结果之类。而另一大类问题就是性能问题。我们可能会发现软件在某些时候运行的非常缓慢,或者在某些机器上运行得非常缓慢,但我们并不知道为什么。现在大家都在拥抱云计算和大数据,这种大规模的生产环境中的诡异问题只会越来越多,很容易占据工程师大部分的时间和精力。大部分问题其实是线上才有的问题,很难复现,或者几乎无法复现。而有些问题出现的比率又很小,只有百分之一、千分之一,甚至更低。我们最好能够不用摘机器下线,不用修改我们的代码或者配置,不用重启服务,在系统还在运行的时候,就把问题分析出来,定位出来,进而采取有针对性的解决办法。如果能做到这一点,那才是完美的,才能每晚都睡上一个好觉。
动态追踪技术实际就能帮助我们实现这种愿景,实现这种梦想,从而极大地解放我们工程师的生产力。我至今还记得当年在雅虎中国工作的时候,有时不得不半夜打车去公司处理线上问题。这显然是非常无奈和挫败的生活和工作方式。如今我工作在美国的一家 CDN 公司,我们的客户也会有自己的运维团队,他们没事就去翻 CDN 提供的原始日志。可能对我们来说是百分之一或者千分之一这样的问题,但是对他们来说就是比较重要的问题,就会报告上来,我们则就必须去排查,必须去找出真正的原因,反馈给他们。这些实际存在的大量的现实问题,激发着新技术的发明和产生。
我觉得动态追踪技术很了不起的一点就是,它是一种“活体分析”技术。就是说,我们的某个程序或者整个软件系统仍然在运行,仍然在线上服务,还在处理真实请求的时候,我们就可以去对它进行分析(不管它自己愿不愿意),就像查询一个数据库一样。这是非常有意思的。很多工程师容易忽略的一点是,正在运行的软件系统本身其实就包含了绝大部分的宝贵信息,就可以被直接当作是一个实时变化的数据库来进行“查询”。当然了,这种特殊的“数据库”须是只读的,否则我们的分析和调试工作就有可能会影响到系统本身的行为,就可能会危害到在线服务。我们可以在操作系统内核的帮助下,从外部发起一系列有针对性的查询,获取关于这个软件系统本身运行过程当中的许多第一手的宝贵的细节信息,从而指导我们的问题分析和性能分析等很多工作。
动态追踪技术通常是基于操作系统内核来实现的。操作系统内核其实可以控制整个软件世界,因为它其实是处于“造物主”这样的一个地位。它拥有绝对的权限,同时它可以确保我们针对软件系统发出的各种“查询”不会影响到软件系统本身的正常运行。换句话说,我们的这种查询必须是足够安全的,是可以在生产系统上大量使用的。把软件系统作为“数据库”进行查询就会涉及到一个查询方式的问题,显然我们并不是通过 SQL 这样的方式去查询这种特殊的“数据库”。
在动态追踪里面一般是通过探针这样的机制来发起查询。我们会在软件系统的某一个层次,或者某几个层次上面,安置一些探针,然后我们会自己定义这些探针所关联的处理程序。这有点像中医里面的针灸,就是说如果我们把软件系统看成是一个人,我们可以往他的一些穴位上扎一些“针”,那么这些针头上面通常会有我们自己定义的一些“传感器”,我们可以自由地采集所需要的那些穴位上的关键信息,然后把这些信息汇总起来,产生可靠的病因诊断和可行的治疗方案。这里的追踪通常涉及两个纬度。一个是时间纬度,因为这个软件还一直在运行,它便有一个在时间线上的连续的变化过程。另一个纬度则是空间纬度,因为可能它涉及到多个不同的进程,包含内核进程,而每个进程经常会有自己的内存空间、进程空间,那么在不同的层次之间,以及在同一层次的内存空间里面,我可以同时沿纵向和横向,获取很多在空间上的宝贵信息。这有点儿像蛛蛛在蛛网上搜索猎物。