Jenkins调优实践
最近一段时间,Jenkins频繁发生FULL GC,耗时在1分钟左右,导致jenkins在1分钟内无法响应任何请求,影响到用户使用。
现象:
从GC日志看,就是在某段时间出现大量对象,且存活时间较长,导致无法回收掉,内存紧张最终触发了长耗时的FULL GC.
调优过程:
第一轮调优:
- 扩大内存。原来堆内存28G,扩到了30G。
- 预留堆内存buffer,对抗突发流量。
- 调高GC吞吐量,让一次GC尽可能的多回收垃圾。
- 增加GC线程,加快回收效率,并让Mix GC提早回收老年代。
- 增加JVM监控,便于观察JVM的行为变化。
结果:其后几天还是出现FULL GC。其中活跃内存在29G上下,接近内存上限,说明内存空间确实不足。
第二轮优化:
这轮其实也谈不上优化,就是想验证下Jenkins到底会吃掉多少内存,最高内存水位线在哪里。于是,就把堆调到40G。
结果:近一个礼拜,没有出现FULL GC, 堆内存峰值在33G左右。这轮调优暂时缓解了问题,争取到了更多的时间去解决问题。
第三轮优化:
通过对堆分析,发现堆内存活对象中有大量的duplicate string,即重复字符串。新增调优参数:-XX:+UseStringDeduplication对重复字符串去重。详细分析请查阅以下 常驻内存的是什么数据?
结果:优化效果显著,内存使用降低了不少, 优化前活跃内存在11G+,优化后活跃内存6G左右。第三轮优化是周五(11/19)晚上22:00左右上线的,优化效果如下图所示:
最后jvm运行参数:
-Xms40G -Xmx40G -XX:+UseG1GC -XX:+UseStringDeduplication -javaagent:/data/soft/jmx/statistic-agent-entry-2.0.0.jar -XX:MaxGCPauseMillis=400 -XX:ConcGCThreads=6 -XX:MarkStackSize=8388608 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=15 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:/data/logs/jenkins/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=15 -XX:GCLogFileSize=2M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/jenkins/jenkins.hprof
jenkins相关知识点:
一:Jenkinsmaster主要工作是什么?
以上主要工作,跟内存紧密相关的就是红框标识的,即“记录并展现构建结果”。其他的跟内存关系不大。
二:常驻内存是什么数据?
通过上一步的分析,其实已经有答案了。这一步只是验证。因产线堆内存大(40G)。所以,不可能在发生OOM的时候,把堆dump下来分析,没有那么大的机器去分析。只能做采样分析,在晚上21:30对堆做了dump分析。通过分析堆,得到堆里的主要内存确实是日志信息,如下:
以上截图是通过heapHero生成。heapHero是一个堆分析工具。
三:如何彻底解决?
单一master的容量总是有上限的,随着构建任务的不断增加,并发量的增大,master终有hold不住的一天,这和软件架构从单一架构向分布式架构转换的道理是一样的。这套jenkins内存消耗高确实是因为构建的量大,jenkins本身并无异常。如果增加配置和调优后仍然无法满足日常的构建需求,建议剥离部分构建作业到新的master/slave集群,分摊压力。
参考资料:
https://www.edureka.co/blog/jenkins-master-and-slave-architecture-a-complete-guide/
https://www.jenkins.io/doc/book/managing/nodes/