Java服务GC参数调优案例

这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题。我个人特别喜欢这种实战类的内容,经原作者的授权同意,将文章分享于此。原文链接:Java服务GC参数调优案例,下面为转载此文的内容,备注部分为本人添加,主要起到说明的作用。

背景以及遇到的问题
我们的Java HTTP服务属于OLTP类型,对成功率和响应时间的要求比较高,在生产环境中出现偶现的成功率突然下降然后又自动恢复的情况,如图所示:

JVM和GC相关的参数如下:

-Xmx22528m
-Xms22528m
-XX:NewRatio=2
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
1
2
3
4
5
6
总结来说,由于服务中大量使用了Cache,所以堆大小开到了22G。GC算法使用CMS(UseConcMarkSweepGC),开启了降低标记停顿(CMSParallelRemarkEnabled),设置年轻代为并行收集(UseParNewGC),年轻代和老年代的比例为1:2 (NewRatio=2).

JVM GC日志相关的参数如下:

-Xloggc:/data/gc.log
-XX:GCLogFileSize=10M
-XX:NumberOfGCLogFiles=10
-XX:+UseGCLogFileRotation
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+DisableExplicitGC
-verbose:gc
1
2
3
4
5
6
7
8
9
问题解决过程
排除应用程序的内存使用问题
首先使用jmap查看内存使用情况:

jmap -histo:live PID
1
这个命令把程序中当前的对象按照个数和占用的空间排序以后打印出来。这里没有发现使用异常的对象。

排除Cache内容过多的问题
如果Cache内容过多也会导致JVM老年代容易被用满导致频繁GC,因此调出GC日志进行查看,发现每次GC以后内存使用一般是从20G降低到5G左右,因此常驻内存的Cache不是导致GC长时间卡顿的根本原因。对于GC LOG的查看有多种方式,使用VisualVM比较直观,需要使用VisualGC:

从图中我们可以看到伊甸园和老年代的空间分配,由于整体内存是20G,设置 -XX:NewRatio=2 因此老年代是14G,伊甸园+S0+S1=7G

调整GC时间点(成功率抖动问题加重)
如果GC需要处理的内存量比较大,执行的时间也就比较长,STW (Stop the World)时间也就更长。按照这个思路调整CMS启动的时间点,希望提早GC,也就是让GC变得更加频繁但是期望每次执行的时间较少。添加了下面这两个参数:

-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=50
1
2
意思是说在Old区使用了50%的时候触发GC。实验后发现GC的频率有所增加,但是每次GC造成的陈功率降低现象并没有减弱,因此弃用这两个参数。

调整对象在年轻代内存中驻留的时间(效果不明显)
如果能够降低老年代GC的频率也可以达到降低GC影响的目的,因此尝试让对象在年轻代内存中进行更长时间的驻留,提升这些对象在年轻代GC时候被销毁的概率。使用参数-XX:MaxTenuringThreshold=31调整以后收效不明显。

备注: 
1、MaxTenuringThreshold 在1.5.0_05之前最大值可以设置为31 ,1.5.0_06以后最大值可以设置为15,超过15会被认为无限大。参考:Never set GC parameter -XX:MaxTenuringThreshold greater than 15 
2、提升年轻代GC被销毁的概率,只是调整这个参数效果不大,第二次age的值会重新计算,参考:说说MaxTenuringThreshold这个参数

CMS-Remark之前强制进行年轻代的GC
首先补充一下CMS的相关知识,在CMS整个过程中有两个步骤是STW的,如图红色部分:

CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:

1、初始标记(CMS-initial-mark),从root对象开始标记存活的对象
2、并发标记(CMS-concurrent-mark)
3、重新标记(CMS-remark),暂停所有应用程序线程,重新标记并发标记阶段遗漏的对象(在并发标记阶段结束后对象状态的更新导致)
4、并发清除(CMS-concurrent-sweep)
5、并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。
通过GC日志和成功率下降的时间点进行比对发现并不是每一次老年代GC都会导致成功率的下降,但是从中发现了一个规律:

前两次GC CMS-Remark过程在4s左右造成了成功率的下降,但是第三次GC并没有对成功率造成明显的影响,CMS-Remark只有0.18s。Java HTTP 服务是通过Nginx进行反向代理的,nginx设置的超时时间是3s,所以如果GC卡顿在3s以内就不会对成功率造成太大的影响。

从GC日志中又发现一个信息:

在文档和相关资料中没有找到蓝色部分的含义,猜测是remark处理的内存量,处理的越多就越慢。添加下面两个参数强制在remark阶段和FULL GC阶段之前先在进行一次年轻代的GC,这样需要进行处理的内存量就不会太多。

备注: 
1、蓝色部分的含义:remark标记需要清理对象的容量。关于如何分析CMS日志,可以参考这篇文章:了解 CMS 垃圾回收日志 
2、FULL GC阶段之前先在进行一次年轻代的GC的意义是:Yong区对象引用了Old区的对象,如果在Old区进行清理之前不进行Yong区清理,就会导致Old区被yong区引用的对象无法释放。可以参考这篇文章:假笨说-又抓了一个导致频繁GC的鬼–数组动态扩容

-XX:+ScavengeBeforeFullGC 
-XX:+CMSScavengeBeforeRemark
1
2
调优以后效果很明显,下面是两台配置完全相同的服务器在同一时间段的成功率和响应时间监控图,第一个没有添加强制年轻代GC的参数。

 


结论
1、在CMS-remark阶段需要对堆中所有的内存对象进行处理,如果在这个阶段之前强制执行一次年轻代的GC会大量减少remark需要处理的内存数量,进而降低JVM卡顿对成功率的影响。 
2、对于Java HTTP服务,JVM的卡顿时间应该小于HTTP客户端的调用超时时间,否则JVM卡顿会对成功率造成影响。

感谢匠心零度对文章内容进行深入的探讨,备注内容属于讨论后的结果
--------------------- 
作者:微笑很纯洁 
来源:CSDN 
原文:https://blog.csdn.net/ityouknow/article/details/79078249 
版权声明:本文为博主原创文章,转载请附上博文链接!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RUNOOB python 67 数组的元素互换

用来练手的Python练习题,原题链接:python练习实例67 题干: 输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组 代码如下: import numpy as nptable np.array([10,4,9,3,11,25,37,15,2,231,672,22]) #定义sw…

11.13 ethtool:查询网卡参数

ethtool命令用于查询或设置网卡参数。ethtool [devname][rootlinuxprobe ~]# ethtool eth0Settings for eth0:Supported ports: [ TP ]Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supported pause frame use: NoSupports au…

微信小程序、微信公众号、H5之间相互跳转

一、小程序和公众号 答案是:可以相互关联。 在微信公众号里可以添加小程序。 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序。已关联的小程序可被使用在自定义菜单和模版消息等场景中。 公众号可关联同主体的10个小程…

数组元素前移后移 RUNOOB python练习题 68

用来练手的python练习题,原题链接: python练习实例68 题干: 有 n 个整数,使其前面各数顺序向后移 m 个位置,最后 m 个数变成最前面的 m 个数 代码如下: import numpy as np # 构造一个储存了n个整数的numpy数组 def numbers_input(n):a n…

LRU缓存简单实现

缓存接口定义 /*** 缓存接口* * author zhi**/ public interface ICache<K, V> {/*** 添加缓存数据* * param key* param value*/void put(K key, V value);/*** 获取缓存数据* * param key* return*/V get(K key);/*** 删除缓存数据* * param key* return*/V remove(K k…

Mac Eclipse安装lombok

Lombok是一个可以通过注解的形式可以帮助消除一些必须但是显得很臃肿的Java代码的工具&#xff0c;通过使用对应的注解&#xff0c;可以在进行编译源码的时候生成对应的方法&#xff0c;比如类属性的get/set/toString()/类的构造方法等. 下面记录一下在Mac Eclipse是如何安装Lo…

tf.reduce_sum()方法深度解析

首先看一下reduce_sum及其参数的注释 : def tf.reduce_sum(input_tensor, axisNone, keepdimsFalse, nameNone) Computes the sum of elements across dimensions of a tensor. Reduces input_tensor along the dimensions given in axis. Unless keepdims is true, the rank o…

主成分分析(PCA)原理详解_转载

一、PCA简介 1. 相关背景 在许多领域的研究与应用中&#xff0c;往往需要对反映事物的多个变量进行大量的观测&#xff0c;收集大量数据以便进行分析寻找规律。多变量大样本无疑会为研究和应用提供了丰富的信息&#xff0c;但也在一定程度上增加了数据采集的工作量&#xff0c;…

Mac cnpm装包时提示Error: EACCES: permission denied解决办法

Cnpm装包时提示Error: EACCES: permission denied解决办法 2018年03月04日 09:31:51 miniminixu 阅读数&#xff1a;1598 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/miniminixu/article/details/79434609 只需在cnpm …

特征点检测 FAST算法及代码详解

本文着重介绍了用于图像特征点检测的算法&#xff0c;FAST算法&#xff0c;以及使用matlab的实现。 FAST算法是一种拐点检测算法&#xff0c;其主要应用于提取图像中的特征点&#xff0c;在动态成像的一系列图像中追踪定位对象。众所周知&#xff0c;我们生活的世界是动态化的…

Python Email发送,通知业务完成

Email 发送 #!/usr/bin/python # -*- coding: UTF-8 -*- import base64 import smtplib from email.mime.text import MIMEText from email.header import Header from email.utils import formataddrdef crypt(source, key):from itertools import cycleresulttempcycle(key)f…

基于SpringCloud的分布式事务框架(LCN)

框架特点 支持各种基于spring的db框架 兼容springcloud、dubbo 使用简单&#xff0c;代码完全开源 基于切面的强一致性事务框架 高可用&#xff0c;模块可以依赖dubbo或springcloud的集群方式做集群化&#xff0c;TxManager也可以做集群化 使用示例 分布式事务发起方&#xf…

一文看懂计算机神经网络与梯度下降

1. 计算机神经网络与神经元 要理解神经网络中的梯度下降算法&#xff0c;首先我们必须清楚神经元的定义。如下图所示&#xff0c;每一个神经元可以由关系式yf(∑i1nwixib)y f(\sum_{i1}^nw_ix_i b)yf(∑i1n​wi​xi​b)来描述&#xff0c;其中X[x1,x2,...,xn]X [x_1,x_2,..…

vs2015web项目无法加载64位c++的dll,提示试图加载不正确的格式

vs2015无法加载64位c的dll&#xff0c;提示试图加载不正确的格式&#xff01; 开始用winform引用64位的c的dll&#xff0c;在项目的属性设置生成里面选择any cpu或者x64都可以成功! 但在web项目和接口里面运行就提示试图加载不正确的格式&#xff0c;想办法找了一天也没处理掉&…

使用Rancher搭建K8S测试环境

环境准备&#xff08;4台主机&#xff0c;Ubuntu16.04Docker1.12.6 SSH&#xff09;&#xff1a; rancher1 192.168.3.160 只做管理节点 node1 192.168.3.161 K8S的节点1 node2 192.168.3.162 K8S的节点2 node3 192.168.3.163 K8S的节点3 此时如…

Anaconda安装tensorflow报错问题解决方法

最近脱离了googlecolab想使用本地的anaconda进行机器学习课题的演练&#xff0c;在安装tensorflow时报错 : UnsatisfiableError: The following specifications were found。下面给出解决方法。 发现实际原因是由于anaconda的python环境&#xff0c;当前版本的tensorflow只能适…

5.07—018—周二

今日所学内容 一、模块 二、递归删除的思路 三、案例&#xff1a;跨文件夹移动文件 四、案例 递归遍历打印目标路径中所有的txt文件 五、项目开放周期 一、模块 1、与时间相关的模块 1&#xff09;time &#xff1a;时间 时间戳(timestamp)&#xff1a;time.time()  延迟线程…

机器学习模型中step与epoch,batch_size之间的关系

本文主要谈谈自己对step&#xff0c;epoch&#xff0c;batch_size这几个常见参数的理解。 最近在调试模型的时候&#xff0c;发现在使用keras.optimizer.adam时&#xff0c;模型在添加了新的一层2D卷积层后难以收敛&#xff0c;在不调整初始权重矩阵的情况下&#xff0c;想通过…

yml的mybatis的sql查看

yml的mybatis的sql查看 控制台输出结果:

Debian 安装 yum

sudo apt-get updatesudo apt-get install build-essentialsudo apt-get install yum转载于:https://www.cnblogs.com/baiqian/p/10840169.html