首页 > 其他分享 >线上服务发布抖动,该怎么解决呢

线上服务发布抖动,该怎么解决呢

时间:2022-10-04 19:11:34浏览次数:67  
标签:服务 阈值 抖动 代码 编译器 编译 JIT 线上 XX

之前的文章分别讲了优雅上线优雅下线,实际工作中做了优雅上下线后,服务发布后还是会有短暂的“抖动”,接口的响应时间急剧升高后又恢复正常,就和下面的监控图一样,图片来源于 得物 的InfoQ技术文档服务发布时网络“抖动”

背景

小卷现在负责的系统已经达到20万QPS了,每天即使是在半夜,QPS依然过万。每次系统升级发布时,抖动比较频繁,上游应用方都跑过来质问,怎么服务又超时了啊,还能不能用了。。。(巴拉巴拉),小卷只能陪着笑脸的一番解释。后来小卷加上了优雅上下线,想着这下发布应该没问题了吧。哪知再次发布,超时问题依然存在。。。小卷决定好好分析一下发布抖动问题的根因是啥

1.抖动问题分析

服务抖动问题需要根据具体场景分析,这里列一下可能的原因:

  • redis、DB连接初始化耗时长,引起启动后的接口RT升高
  • JIT即时编译耗时长,造成CPU利用率高,引起接口RT升高

对于高并发的应用来说,这里JIT即时编译是通用的原因。

JIT是什么?

JIT(just-in-time)即时编译,是一种执行计算机代码的方法,这种方法涉及在程序执行过程中(在执行期)而不是在执行之前进行。关于JIT的历史,摘抄一段维基百科上的内容

最早发布的JIT编译器是 约翰·麦卡锡在1960年对LISP的研究。在他的重要论文《符号表达式的递归函数及其在机器上的计算》(Recursive functions of symbolic expressions and their computation by machine, Part I)提到了在运行时被转换的函数,因此不需要保存编译器输出来打孔卡。在Self被Sun公司抛弃后,研究转向了Java语言。“即时编译”这个术语是从制造术语“及时”中借来的,并由Java普及,Java之父James Gosling从1993年开始使用这个术语。目前,大多数Java虚拟机的实现都使用JIT技术,而且使用广泛。

了解JVM的都知道,Java的编译分为两部分:

  • javac.java文件编译为.class文件,即转换为字节码
  • 解释器将.class字节码文件解释为机器码(0、1)执行

但是解释执行的缺点很明显,执行速度慢。

Java早期使用解释执行,将字节码逐条解释执行,这种方式运行很慢。如果是快速反复调用某段代码,执行效率大大降低。后来为了解决这种问题,JVM引入了JIT即时编译,当Java虚拟机发现某段代码块或是方法执行比较频繁,超过设定的阈值时,就会把这些代码视为热点代码(Hot Spot code)

为了提高热点代码的执行效率,虚拟机会将其编译为机器码,并存到CodeCache里,等到下次再执行这段代码时,直接从CodeCache里取,直接执行,大大提升了运行效率,整个执行过程如下:

看上图很容易理解JIT是什么,然后思考下面的问题:

  • 怎么判断属于热点代码?
  • 阈值是怎么设定的?
  • codeCache又是什么?

怎么判断热点代码

我们知道JIT是将热点代码编译成机器码缓存起来的,那么什么样的代码才属于热点代码呢

HotSpot虚拟机使用的是基于计数器的热点代码探测,JVM统计每个方法调用栈的弹出频率作为指标,提供了2种次数级别热点探测方法:

  1. 精确计数,超过阈值触发编译 (统计的是总调用量)
  2. 记录一段时间内被调用的次数,超过阈值触发编译(类似QPS的含义)

JVM默认使用的第二种方法统计方法调用次数,因为第一种方法计算开销大,第二种方法与调用时间有关,适用于大多数场景

阈值如何设定

上面说到超过阈值才触发编译,阈值是设置为多少了呢?

先说说JVM的分层编译器,Hotspot虚拟机中,JIT有2种编译器C1编译器(客户端模式)、C2编译器(服务端模式)。

C1编译器:简单快速,搜集信息较少,主要关注点在局部化的优化,编译速度快,适用于对启动性能有要求的应用。缺点是编译后的代码执行效率低;

C2编译器:需要搜集大量的统计信息在编译时进行优化,为长期运行的应用程序做性能优化的编译器,优化手段复杂,编译时间长,编译出来的机器码执行效率高。代价是启动时间变长,程序需要执行较长时间后,才能达到最佳性能;

JAVA8之后默认开启了分层编译,即:应用启动初期使用C1编译器缓存热点代码,在系统稳定后使用C2编译器继续优化性能。

可通过一些参数进行设置

在 Java8 中默认开启分层编译(-XX:+TieredCompilation默认为true)

  • 如果只想用 C1,可以在打开分层编译的同时使用参数“-XX:TieredStopAtLevel=1”
  • 如果只想用 C2,使用参数“-XX:-TieredCompilation=false”关闭分层编译即可

通过java -version可看到当前JVM使用的编译模式

方法被调用的次数,在 C1 模式下默认阈值是 1500 次,在 C2 模式是 10000 次,可通过参数-XX: CompileThreshold 手动设定,在分层编译的情况下,-XX: CompileThreshold 指定的阈值将失效,此时将会根据当前待编译的方法数以及编译线程数来动态调整。超过阈值触发编译,编译完成后系统会把方法调用入口改为最新地址,下次直接使用机器码。

需要注意的是,计数器统计的是一段时间内的调用次数,当超过时间限度调用次数仍然未达到阈值,那么该方法的调用次数就会减半,并不是一直累加的,这段时间称为该方法的统计半衰周期,可以使用虚拟机参数-XX:-UseCounterDecay 关闭热度衰减,参数-XX:CounterHalfLifeTime 设置半衰周期的时间,需要注意进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的。

CodeCache是什么

CodeCache主要用于存储JIT编译后的机器码,随着程序的运行,大部分热点代码都会编译为机器码来运行。所以Java的运行速度比较快,除了JIT编译的代码外,本地方法代码(JNI)也会存储在Codecache内。可配置一些参数设置Codecache的属性

  • -XX:ReservedCodeCacheSize:codeCache最大大小
  • -XX:InitialCodeCacheSize:codeCache初始大小

在Linux环境下,Codecache默认大小是2.4375M,可通过jinfo -flag InitialCodeCacheSize [java进程ID]查看,如图

2.为什么应用刚启动时会抖动?

上面已经讲了JIT即时编译,这样也好理解为什么刚启动完的应用,RT突然升高,CPU利用率也很高。在高并发场景下,一个方法的调用次数激增,会瞬间达到JIT编译的阈值,JVM会执行即时编译,讲热点代码转为机器码。热点代码过多时,JIT编译的压力会增大,造成系统的load升高,CPU利用率跟着升高,导致服务的整体性能下降

3.解决方案

这里小卷列了一些解决方案,需要根据具体场景具体使用,如图

JWarmup

AJDK内嵌的功能模块,相关wiki在阿里的Github上阿里巴巴Dragonwell8用户指南

其原理是先发布beta服务器,等到beta服务器的JIT编译完成后,将热点方法dump下来,然后production环境发布时直接加载dump文件,不需要再进行JIT编译了。从JVM层面解决了该问题,但是接入门槛较高,可能会踩一些坑。

平台预热

借助流量调度平台的能力,小流量预热后再放开,把JIT编译的影响降低。是综合考虑接入成本以及推广维护最合适的方案。这里阿里云微服务引擎MSE已提供功能小流量预热服务,但是是收费的哦~

关注我

我是卷福同学,公众号同名,在福报厂修福报的小卷哦~

标签:服务,阈值,抖动,代码,编译器,编译,JIT,线上,XX
From: https://www.cnblogs.com/dnboy/p/16754245.html

相关文章

  • centos 7 设置 docker 开机自启服务
    centos7设置docker开机自启服务[[email protected]]#systemctllist-unit-files#查看开机自启项列表UNITFILESTATE......
  • 118-22-ZooKeeper 基础设施详解 和 服务启动流程源码分析_ev
         ......
  • 音视频服务质量指标
    除了实时通信延迟指标外,音视频通信中还有业务服务质量指标,包括音频服务质量和视频服务质量。由于音频数据量比较小,受网络的影响不大,并且3A问题非常复杂,这里就不介绍了。接......
  • 关于MC服务器的优化启动
    azul的zing优化jdk可以免费体验实际使用的时候却发现经常闪退,需要用以下参数运行java-Xms10G-Xmx10G-XX:+UseShenandoahGC-XX:+UseTrueObjectsForUnsafe-XX:+Paral......
  • windows安装gitbook服务中遇到的错误
    windows安装gitbook服务中遇到的错误最近因为不太喜欢没有目录的Hexo网站了,又开始重新弄gitbook。这里记录一下安装过程中的错误。yarn安装gitbook服务使用命令yar......
  • 查看MySQL服务
    MySQL的服务在哪里:计算机-->右键-->管理-->服务和应用程序-->服务-->找MySQL服务MySQL的服务,默认是“启动”的状态,只有启动了mysql才能用默认情况下是“自动”启动,自动......
  • 集群JournalNode服务重启导致NameNode挂掉分析
    温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。Fayson的github:​​https://github.com/fayson/cdhproject​​提示:代码块部分可......
  • 最简单搭建前端轻量级项目开发服务
    本文讨论了如何搭建一个简单的前端项目开发服务,这个服务要实现以下几点:Javascript的打包压缩;scss的编译打包压缩;简单文件http服务;监测文件变化自动刷新浏览器;零......
  • 阿里云服务器中MySQL数据库被攻击
    前几天刚领了一个月的阿里云服务器玩,在里面装了MySQL,然后这几天找了个小项目练习着玩呢,就将表建在里面了。刚访问添加员工还好好的,刚给员工分页查询呢,啪一下,很突然昂,就......
  • 苏州十大IDC机房排名,苏州idc服务商实力排名
       随着新基建、5G、云计算、东数西算建设的加速,IDC产业作为数字化基础设施的关键迎来了发展黄金阶段,本文将介绍2022年我国长三角核心城市--苏州IDC数据中心及IDC服务......