1.背景
部署Elasticsearch服务,主要提供记录用户登录日志、访问日志,统计,查询等功能。
遇到的问题为:
- 平稳运行时CPU使用率为20%左右,当批量更新定时任务执行时,
CPU使用率激增到60%左右,最高值到达90%,服务器监控系统开始报警。
- Elasticsearch长时间运行,内存占用率大幅提高,严重影响功能使用,需要在内存占用较大时重启ES服务。
2.定位CPU使用率高问题以及解决办法
Elasticsearch是基于java开发的,先查看elasticsearch进程的运行情况,然后查看jvm相关参数。生产环境问题已解决(部分问题暂时无法提供截图说明)
1.定位到具体问题
使用jstat -gcutil pid 1000 命令查看垃圾回收情况
可知每两秒进行一次minor GC,定位问题为频繁的minor GC 引起的cpu使用率居高不下。
2.查看垃圾回收器和内存分配情况
1.确定垃圾回收器的使用
生产环境使用jdk版本为jdk11,jvm.options文件中相关参数表明
在jdk8-13默认使用的垃圾回收算法为CMS,因为CMS为老年代垃圾收集器,默认与之配合使用的新生代垃圾回收器为ParNew。
使用jps命令找到ES运行的进程id
使用jinfo命令 查看jvm的相关参数,确认使用的垃圾回收器为ParNew+CMS。
2.查看heap大小分配情况
服务器内存为16g,根据官方推荐heap大小配置不宜超过8g
jvm.options配置参数为
-Xmx7g
-Xms7g
没有显示声明新生代的大小,CMS垃圾回收器新生代默认大小为:
max_heap/(NewRatio+1)和ScaleForWordSize(young_gen_per_worker * parallel_gc_threads) 中最小的值。
max_heap/(NewRatio+1) 即最大堆内存/(2+1) (未显式设置参数NewRatio 则默认为2) 7*1024/3=2389.33M
ScaleForWordSize(young_gen_per_worker * parallel_gc_threads) 计算公式为 young_gen_per_worker * parallel_gc_threads * 13/10
young_gen_per_worker 的值x86机器为64M,parallel_gc_threads简单的理解为cpu核数8 64*8*13/10=665M
即最后的新生代大小为665M
使用jstat -gc 查看内存分配情况 新生代为665M,
默认参数-XX:SurvivorRatio=8 即Eden:S0:S1=8:1:1 可知Eden内存大小为532M
可知新生代内存设置太小,Eden区满了之后会进行频繁的minor GC导致Cpu占用率提高
3.解决办法
1.显式设置参数-Xmn 由于老年代占用比例较小,且在minor GC 过程中晋升到老年代的对象较少,所以可以提高新生代的内存占比设置为-Xmn4g
2.改用G1垃圾回收器,可在垃圾回收过程中根据使用情况动态改变新生代的大小
3.定位Elasticsearch长时间运行,内存占用率高问题以及解决办法
CMS会在垃圾回收过程中产生内存碎片,不利于程序的长时间运行。
而G1在运行期间不会产生内存碎片,有利于程序长时间运行。
综上所述,从两个方面来看以及生产环境的试运行情况来看,选择修改垃圾回收器为G1的解决方案。
总结,修改垃圾回收器为G1后,平稳期cpu使用率稳定在5%以下。