谈谈Java应用发布时CPU抖动的优化

研究背景

通常情况下应用发布或重启时都存在cpu抖动飙高,甚至打满的现象,这是由于应用启动时,JVM重新进行类加载与对象的初始化,CPU在整个过程中需要进行比平时更多的编译工作。同样,闲鱼的消息系统在重新发布时经常有抖动的问题,如下图显示:日常情况下CPU使用率基本不超过20%,而每当应用重新发布时,服务器的cpu使用率骤增至40%以上。本文正是为了减少这种抖动,进而保障应用发布时的稳定性。

0c9203fb0b507940e0ee168ac57916fd.png

Java的编译

发布时CPU利用率的飙高很大程度上是编译造成的,因此在处理问题之前,我们需要了解Java编译的机制,这对于后续的理解很重要。如果已经该部分知识非常熟悉,则可以跳过本节直接阅读第三部分。常见的编译型语言如C++,通常会把代码直接编译成CPU所能理解的机器码来运行。然而为了实现“一次编译,处处运行”的特性。

Java把编译的过程分成两个阶段

  • • 先由javac编译成通用的中间形式(字节码),该阶段通常被称为编译期。

  • • 解释器逐条将字节码解释为机器码来执行,该阶段则属于运行期。

为了优化Java字节码运行的性能 ,HotSpot在解释器之外引入了JIT(Just In Time)即时编译器,形成了用解释器+JIT编译器混合的执行引擎

二者会在运行期并肩作战,但分工不同

  • • 解释器(Interpreter):当程序需要迅速启动时,使用解释器解释字节码,节省编译的时间,快速执行。

  • • JIT编译器(JIT Compiler):在程序启动后并且长时间提供服务时,JIT将越来越多的代码编译为本地机器码,获得更高的执行效率。

Java程序在JVM上执行的过程如下图所示:

76cfb1fe2fed38cc8967030bed88ec43.png

编译期先由javac将源码编译成字节码,在这个过程中会进行词法分析、语法分析、语义分析等操作,该过程也被称为前端编译。当类加载完成,程序运行时,JVM会利用热点代码计数器进行判断,如果此时运行的代码是热点代码则使用JIT,如果不是则使用解释器。对于热点代码的判断方式有采样估计和计数两种方式,Hotspot采用计数方式,到达一定阈值时触发编译。

大多数情况下解释器首先发挥作用,将字节码按条解释执行。随着时间推移,通过不断对解释的代码进行信息采集,JIT逐渐发挥作用。把越来越多的字节码编译优化为本地机器码并存储在CodeCache中,来获取更高的执行效率。解释器这时可以作为编译运行的降级手段,在一些不可靠的编译优化出现问题时,再切换回解释执行,保证程序可以正常运行。JIT极大地提高了Java程序的运行速度,而且跟静态编译相比,即时编译器可以选择性地编译热点代码,省去了很多编译时间,也节省很多的空间。

定位问题

在线诊断

Arthas 是阿里巴巴推出的一款免费的线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息。首先,我们使用Arthas在预发环境下连接服务器,进而对对常规时刻的CPU使用率进行监控,操作步骤如下:

下载:>> curl -O https://arthas.aliyun.com/arthas-boot.jar  启动:>> java -jar arthas-boot.jar 看板:>> dashboard

dashboard面板显示如下图,可以看到此时的各线程所占用的CPU。随后,我们进行应用的发布重启,来观察该过程的CPU使用率变化,下图是常规时段的CPU利用率。

1d5b7a94ec875ae7cb01f9c4b642ff5c.png

随后我们开始发布应用。开始发布后不久搭建的ssh链接会被服务器断开,此时应用被停止。在连接断开之前捕捉到了如下记录,“VM Thread”等线程,占用了一定的的CPU,但不是很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值