Go语言精进之路:从新手到高手的编程思想、方法和技巧(2)
上QQ阅读APP看书,第一时间看更新

第48条
使用expvar输出度量数据,辅助定位性能瓶颈点

上一条提到,要想对Go应用存在的性能瓶颈进行剖析,首先就要对不同类型的性能数据进行收集和采样。有两种收集和采样数据的方法。在微观层面,采用通过运行性能基准测试收集和采样数据的方法,这种方法适用于定位函数或方法实现中存在性能瓶颈点的情形;在宏观层面,采用独立程序收集和采样数据的方法。但通过独立程序进行性能数据采样时,往往很难快速捕捉到真正的瓶颈点,尤其是对于那些内部结构复杂、业务逻辑过多、内部有较多并发的Go程序。我们在对这样的程序进行性能采样时,真正的瓶颈点很可能被其他数据遮盖。

那么如何能更高效地捕捉到应用的性能瓶颈点呢?我们需要知道Go应用运行的状态。应用运行状态一般以度量数据的形式呈现。通过了解应用关键路径上的度量数据,我们可以确定在某个度量点上应用的性能是符合预期性能指标还是较大偏离预期,这样就可以最大限度地缩小性能瓶颈点的搜索范围,从而快速定位应用中的瓶颈点并进行优化。

这些可以反映应用运行状态的数据也被称为应用的内省(introspection)数据。相比于通过查询应用外部特征而获取的探针类(probing)数据(比如查看应用某端口是否有响应并返回正确的数据或状态码),内省数据可以传达更为丰富、更多的有关应用程序状态的上下文信息。这些上下文信息可以是应用对各类资源的占用信息,比如应用运行占用了多少内存空间,也可以是自定义的性能指标信息,比如单位时间处理的外部请求数量、应答延迟、队列积压量等。

传统编程语言(如C++、Java等)并没有内置输出应用状态度量数据的设施(接口方式、指标定义方法、数据输出格式等),需要开发者自己通过编码实现或利用第三方库实现。Go是“自带电池”的编程语言,我们可以轻松地使用Go标准库提供的expvar包按统一接口、统一数据格式、一致的指标定义方法输出自定义的度量数据。在本条中,我们就一起来看看如何使用expvar输出自定义的性能度量数据。