(转) 发布或重启线上服务时抖动问题解决方案

转自 http://www.cnblogs.com/LBSer/p/3703967.html

相关:

load、jstack、Java编译、Java运行模式

一、问题描述

      在发布或重启某线上某服务时(jetty8作为服务器),常常发现有些机器的load会飙到非常高(高达70),并持续较长一段时间(5分钟)后回落(图1),与此同时响应时间曲线(图2)也与load曲线一致。注:load飙高的初始时刻是应用服务端口打开,流量打入时(Load指的是运行队列(run-queue)的长度:L=等待进程的数目+运行进程的数目,具体指什么可参考http://www.cnblogs.com/amsun/p/3155246.html )。

图1 发布时候load飙高

图2 发布时候响应时间飙高

二、问题排查方法

发布时对资源使用情况进行监控。

1)通过top -H -p 查找cpu使用率较高的线程,发现2129和2130这两个线程cpu使用较高。

图3 查找cpu使用率较高的线程

2)通过jstack打印栈信息,并将线程号2129和2130转换成16进制(printf "%x\n" 2129),分别为851和852,发现这两个线程是编译线程(表1)。此外当这两个线程cpu使用率降低后load以及响应时间也马上恢复了正常,时间点非常吻合。

表1 cpu使用率较高的两个线程详细信息


1

2

3

4

5

6

7

8

"C2 CompilerThread1" daemon prio=10 tid=0x00007fce48125800 nid=0x852 waiting on condition [0x0000000000000000]

java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:

- None

"C2 CompilerThread0" daemon prio=10 tid=0x00007fce48123000 nid=0x851 waiting on condition [0x0000000000000000]

java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:

- None

三、现象解释

C2 CompilerThread线程项目启动初期cpu使用率那么高,它在干什么呢?

Java程序在启动的时候所有代码的执行都处于解释执行模式,只有在运行了一段时间后,根据代码方法执行的次数,或代码里循环的执行次数等达到一定的阈值才会编译成机器码,编译成机器码后执行效率会得到大幅提升,而随着执行时间进一步拉长,JVM的各种更高级的编译优化手段就会逐渐加上,例如if条件的执行状况,逃逸分析等。这里的C2 CompilerThread线程干的就是编译优化的活。

现在貌似可以解释之前的现象了。

在程序刚启动的时候,java还处于解释执行模式,因此服务效率很低,响应时间缓慢,处理得慢了,load自然也就高了。而当流量持续不断导入时,我们代码的很多方法执行次数不断增多,此时C2 CompilerThread线程不断收集优化信息,并且开始将一些热点代码优化编译成本地机器码,因此该线程的cpu使用率增高。而当C2 CompilerThread线程完成初始编译优化过程后,C2 CompilerThread线程的cpu使用率开始下降,与此同时优化后服务的性能大幅提升,服务响应时间也大大缩短,load也下降。

现在的症结在于编译优化过程持续时间较长,引起抖动如何降低编译优化的持续时间呢?

四、解决思路

1)预热

如果在服务接受线上请求之前提前完成编译优化过程,那么将能避免此种抖动情况。一般的做法是预热,有两种方法:

a)程序主动预热:在启动完成后,程序主动的访问热点的代码,确保主要的热点代码已被编译成机器码后再放入流量,可通过-XX:+PrintCompilation来确认。

b)复制流量预热:通过tcpcopy软件拷贝一份线上nginx的流量进行预热,完成之后再导入线上流量。

2)启动多个线程进行编译优化

如果能加快编译优化速度,那也能降低解释执行阶段导致的抖动时间。因此可以多拿几个线程来做编译,加快达到高峰性能的速度。

可以使用-XX:CICompilerCount参数来设置编译线程数目,这个值默认是2(之前在栈里看到有两个编译线程),我们可以加到4。

3)采用多层编译

编译方式有三种:1)Client模式;2)Server模式;3)Tiered模式。我们服务默认是Server模式。

Server模式是采用c2高级编译的,会比较耗时且要运行一段时间才会触发编译。 Server模式的优点是编译后程序效率较高;

Client模式比较轻量也比较快触发(比Server模式触发快),编译优化后程序效率不如Server模式;

Tiered模式是Client模式和Server模式的折中,一开始会启用Client模式,可以在启动后更快的让部分代码先进入编译优化阶段,之后会启动Server模式,达到程序效率最大优化的目的。

Oracle JDK 7里的HotSpot VM已经开始有比较好的Tiered编译(tiered compilation)支持,可以设置参数-XX:+TieredCompilation来启动Tiered模式,java 8默认就是Tiered模式。

图4是到http://www.javaworld.com/article/2078635/enterprise-middleware/jvm-performance-optimization--part-2--compilers.html截取的不同编译方式的性能比较图,横坐标是时间,纵坐标是性能。可以看出Tired模式开始阶段性能与C1相当,当到达某一时刻后性能与C2相当。

图4 不同编译模式的性能比较

五、结果分析

简单起见采用方案2和方案3来进行优化。

采用方案2和3之后进行了多次发布,发布时除个别机器load达到10之外,基本没有过高现象(在2~4范围内),并且短时间(2分钟)内,load都会降到较合理水平(2左右),较发布时的load来看,比优化前要好很多。

方案2和方案3只是降低了抖动持续的时间以及抖动强度,并不能完全避免抖动。真正能避免抖动的方案应该是方案1,通过预热的方式实现平滑发布或重启。

时间: 2024-10-01 03:00:56

(转) 发布或重启线上服务时抖动问题解决方案的相关文章

发布或重启线上服务时抖动问题解决方案

发布或重启线上服务时抖动问题解决方案 一.问题描述       在发布或重启某线上某服务时(jetty8作为服务器),常常发现有些机器的load会飙到非常高(高达70),并持续较长一段时间(5分钟)后回落(图1),与此同时响应时间曲线(图2)也与load曲线一致.注:load飙高的初始时刻是应用服务端口打开,流量打入时(load具体指什么可参考http://www.cnblogs.com/amsun/p/3155246.html). 图1 发布时候load飙高 图2 发布时候响应时间飙高 二.问

软件开发交易线上服务_威客平台

革新威客行业的软件开发线上服务交易平台--大大神,在威客行业中现在主要的模式是以移动互联网+线上服务交易+任务发布为主的行业模式.威客行业在不断扩张,但却没有突破重围,达到一个新的高度.大大神平台作为了领先人物突破了威客行业的这个重围.什么是威客?威客是指通过互联网把自己的智慧.知识.能力.经验转换成实际收益的人,他们在互联网上通过解决科学,技术,工作,生活,学习中的问题从而让知识.智慧.经验.技能体现经济价值.因为诚信和制度的问题存在很大弊病,导致工作者成廉价劳动力,各种欺骗行为层出不穷.目前

Linux(2)---记录一次线上服务 CPU 100%的排查过程

Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过日志输出错误信息: 得知websocket时时重新 连接的信息,然后找到原因 解决了. 当然这里幸好能通过日志大致分析出原因 那么我就在思考如果日志没有告诉任何信息 但线上CPU还是接近100%那么如何排查呢.所以学习了下排查过程. 通过查阅资料并实践后,这里总结了两种办法.第一种博客满天飞的方法

线上服务应急与技术攻关方法论

海恩法则和墨菲定律 海恩法则指出: 每一起严重事故的背后,必然有29次轻微事故和300起未遂先兆以及1000起事故隐患. 海恩法则强调两点: (1)事故的发生是量的积累的结果: (2)再好的技术,再完美的规章,在实际操作层面,也无法取代人自身的素质和责任心. 根据海恩法则,一起重大事故发生之后,我们要在处理事故和解决问题的同事,还要及时的对同类问题的「事故征兆」和「事故苗头」进行排查并处理,以防止类似问题的再次发生,将问题在萌芽状态就将其解决掉,这可以作为互联网企业线上应急的指导思想. 墨菲定律

线上服务CPU100%问题快速定位实战--转

来自微信公众号 架构师之路 功能问题,通过日志,单步调试相对比较好定位. 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底. 58到家架构部,运维部,58速运技术部联合进行了一次线上服务CPU问题排查实战演练,同学们反馈有收获,特将实战演练的试题和答案公布出来,希望对大家也有帮助. 题目 某服务器上部署了若干tomcat实例,即若干垂直切分的Java站点服务,以及若干Java微服务,突然收到运维的CPU异常告警. 问:如何定位是哪个服务进程导致CPU

vue-router+webpack线上部署时单页项目路由,刷新页面出现404问题

使用vue项目,线上部署的时候,访问首页以及通过路由打开二级页面没有问题,但是一刷新就出现404现象 因为刷新页面时访问的资源在服务端找不到,因为vue-router设置的路由不是真实存在的路径. 解决办法是:在nginx.conf配置修改如下: location / { root html; try_files $uri $uri/ @router; index index.html index.htm; } location @router { rewrite ^.*$ /index.htm

线上服务 CPU 100%?一键定位 so easy!

转自:  https://my.oschina.net/leejun2005/blog/1524687 摘要: 本文主要针对 Java 服务而言 0.背景 经常做后端服务开发的同学,或多或少都遇到过 CPU 负载特别高的问题.尤其是在周末或大半夜,突然群里有人反馈线上机器负载特别高,不熟悉定位流程和思路的同学可能登上服务器一通手忙脚乱,定位过程百转千回. 对此,也有不少同学曾经整理过相关流程或方法论,类似把大象放进冰箱要几步,传统的方案一般是4步: top oder by with P:1040

一种线上服务日志切分与压缩方法

1.业务背景 对于线上业务而言,打印日志是一个系统运行状况的全面体检,日志打得约详细,越容易查找问题,但是机器磁盘是有限的,这时候很容易将磁盘撑爆.所以打印日志多少要选取一个平衡,打印适量的日志,只在关键环节,容易出错的地方打印日志即可.但是随着业务量的提升,即使我们控制了打印日志的频率,但日志文件的容量也在大量扩大.如果我们对日志文件的处理方式不当,日志文件将打到磁盘上线,新业务就再也刷不出来任何日志了. 因此,我们对日志的处理一般分为三个步骤: 打印当天日志,历史日志重命名为带日期格式,以示

java线上服务问题排查

1.业务日志相关 如果系统出现异常或者业务有异常,首先想到的都是查看业务日志 查看日志工具: less 或者more grep tail -f filename 查看实时的最新内容 ps:切忌vim直接打开大日志文件,因为会直接加载到内存的 2.数据库相关 java应用很多瓶颈在数据库,一条sql没写好导致慢查询,可能就会带来应用带来致命危害. 如果出现Could not get JDBC Connection .接口响应慢.线程打满等, 需要登录线上库, 查看数据库连接情况:show proc