continuous profiling在分布式任务的应用

268 阅读6分钟

continuous profiling

continuous profiling 区别于传统的按需诊断方式。他的特点是持续采样,因为持续的特点,所以要比按需诊断的模式更加低消耗,否则continuous profiling 一开启,处理业务的进程吞吐下降,反而影响了业务能力。

continuous profiling和Google Wide Profiling的区别

目前可追溯到continuous profiling的起源,就是在Google Wide Profiling的论文中。但是现在的发展和论文的使用有了非常大的区别。

Google Wide Profiling中主要目的是找出数据中心的改进点,基于这个目标,他的采样更加低频,同时基于采样的准则,可以随机的触发,只要时间足够久。采集的堆栈的热点的结论是相对可信的。

目前市面上的continuous profiling重点放在了问题诊断上。从产品形态和目的上,更接近open telemetry。作为trace,metric,log的补充存在。这里比较好理解,举个进程卡主的例子

  • trace依赖埋点和进程的上报,假如链路节点没有上报,例如卡主的情况,其实这里只知道他一定出问题在2个节点中间,具体是什么不知道。
  • log依赖日志编写,本质也是埋点的一种。和trace的主要区别在于,trace更偏向框架,协议,而且可以跨进程展示。log更接近业务编写本身,改代码就能加。他的缺点也同trace。
  • metric更是指标的统计。只能知道有变化,并不能提供详细的数据。

基于上面的3个手段的盲点,telemetry可以通过采集堆栈加时间点的对齐,来告诉用户中间可能发生了什么。因为手段是采样,所以能覆盖的场景,必须是有一定时间停留或者是发生次数足够多。这也是目前主流的应用方向。

大数据场景的应用

在笔者的开发场景中,找到了短job或者是流式任务在continuous profiling的应用。看到这里大家可能会感到奇怪大数据都发展这么多年了,分布式任务已经有很多成熟的方案了,为什么我要应用这个场景。 大数据服务大多数都是Java编写,这就离不开jvm本身的发展了。

大数据任务观测能力的变更

任何一个程序,一定离不开2个重点观察点。第一个是cpu,第二个是内存。
时代方案1
在jvm早期的解决方案是偏向传统的native程序。perf-map-agent。通过把jit的信息映射出来,结合perf抓cpu,alloc堆栈。这种方式是一种外部触发的方式,比较依赖外部的操作。分布式任务的随机性,导致了这个方案不是很好用。任务很随机的启动在不同的机器上,如何去知道哪些的进程应该去抓取。

时代方案2
方案2使用了jvmti,通过javaagent的方式解决了任务随机的问题。只要自己的任务指定了javaagent。启动的时候可以带上agent,agent来采集自身的指标进行汇报。业界著名的分布式工具都是这个解决方式,例如babar,uber profiling。他虽然了启动的不确定带来的问题,但是同时受限于javaagent的能力。基本能做到的就是做个堆栈的定期截取。这个虽然能提供一定的信息了,本身是wall clock堆栈,他不携带任何的特殊信息,例如那个堆栈分配内存多,那个堆栈耗费cpu问题。当然还有著名的safepoint bias问题,只不过相比能力的缺失,这个问题反而小了一些。jvmti在11上提供了分配观测的能力,不过要编写native agent。对代码编写有一定的考验,业界也没有好的开源产品。商业版本是有的,因为付费,推广也不是很好。

时代方案3
上述的方案已经进步到jdk11了,在11上同时增加了另外一个重磅功能:jfr。jfr之前是收费的功能,11上正式开源了。cpu,memory的采集已经内置了,直接定期的生产jfr文件就可以上传分析了。在jdk14的时候提供了jfr streaming功能。原来的落磁盘文件再解析的方案可以更优雅,直接用streaming实时解析jvm生成的event,直接发送。

这里好像有点反直觉,现在我们java的continuous profiling明明是支持java8的,按照上面的流程至少11才能使用才对。这里就感谢openjdk社区的大佬们,把11上的jfr推动合并到8上了。我们才能享受到对应的能力。

以上的3种方案在现在的开源方案中都可以见到。方案1的使用方式因为和native接近,所以可以直接依赖ebpf的模式,可以结合系统能力获取更多的观测。方案2的主流现在是依赖ayncprofiler来做,规避的一些付费的问题,overhead也可以控制。方案3主要是去规避ayncprofiler的不稳定性。而且overhead更低,但是失去了native的观测能力,方案也限制在了纯java应用。

核心能力的演变

Brendan gregg 开始创作了火焰图的展示形式。给找特点提供了很大的便利。而且火焰图也开始各种变种例如diff,time,mixed等等。火焰图的维度也增加了,例如alloc,cpu,lock等等。
现在continuous profiling主要提供的功能就是做多进程的合并火焰图,不同时间,不同进程的diff火焰图。
这个也就导致了解决问题的多样性出来了。

场景回顾

大数据的分布式任务,只要观测到cpu,alloc,lock 基本的这三个能力。在低消耗的采集堆栈,合并就可以看到整体的性能堆栈,分开就可以通过diff找出不同进程的不同点。这样看能解决大数据的问题,还有空缺的一些点,例如io,socket可以弥补cpu采集不到的case。

总结

continuous profiling在新的采样技术的发展下,也更适合作为大数据场景下的诊断分析,使用的场景更聚焦在堆栈的合并和找差异上。