Appearance
背景
目前本公司JVM有比较多参数,属于继承了原始OMS系统的参数来源,一直沿用至今;随着时间的推移,JVM参数随着公司业务的壮大,系统流量与复杂度的增加,所有配置方面需要更规范,更标准化,使得未来系统更加的健壮与稳定运行,做到未雨绸缪
参数说明
调优栈内存
表 1. 堆大小典型配置参数
配置参数 | 说明 | 示例 |
---|---|---|
-Xmx | 设置最大堆大小。 | -Xmx3550m,设置JVM最大可用内存为3550 MB。 |
-Xms | 设置JVM初始内存。 | -Xms3550m,设置JVM初始内存为3550 MB。此值建议与-Xmx相同,避免每次垃圾回收完成后JVM重新分配内存。 |
-Xmn2g | 设置年轻代大小。 | -Xmn2g,设置年轻代大小为2 GB。整个JVM内存大小=年轻代大小+年老代大小+持久代大小。持久代一般固定大小为64 MB,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 |
-Xss | 设置线程的栈大小。 | -Xss128k,设置每个线程的栈大小为128 KB。 |
说明 JDK 5.0版本以后每个线程栈大小为1 MB,JDK 5.0以前版本每个线程栈大小为256 KB。请依据应用的线程所需内存大小进行调整。在相同物理内存下,减小该值可以生成更多的线程。但是操作系统对一个进程内的线程个数有一定的限制,无法无限生成,一般在3000个~5000个。 | ||
-XX:NewRatio=n | 设置年轻代和年老代的比值。 | -XX:NewRatio=4,设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。如果设置为4,那么年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。 |
-XX:SurvivorRatio=n | 年轻代中Eden区与两个Survivor区的比值。 | -XX:SurvivorRatio=4,设置年轻代中Eden区与Survivor区的大小比值。如果设置为4,那么两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。 |
-XX:MaxPermSize=n | 设置持久代大小。 | -XX:MaxPermSize=16m,设置持久代大小为16 MB。 |
-XX:MaxTenuringThreshold=n | 设置垃圾最大年龄。 | -XX:MaxTenuringThreshold=0,设置垃圾最大年龄。 |
调优回收器GC
表 2. 吞吐量优先的GC典型配置参数
配置参数 | 说明 | 示例 |
---|---|---|
-XX:ParallelGCThreads | 配置并行收集器的线程数,即同时多少个线程一起进行垃圾回收。 | |
说明 此值建议配置与处理器数目相等。 | -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20,-XX:ParallelGCThreads=20表示配置并行收集器的线程数为20个。 | |
-XX:MaxGCPauseMillis | 设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。 | -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100,-XX:MaxGCPauseMillis=100设置每次年轻代垃圾回收的最长时间为100 ms。 |
-XX:+UseParallelOldGC | 配置年老代垃圾收集方式为并行收集。 | |
说明 JDK 6.0支持对年老代并行收集。 | -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC,-XX:+UseParallelOldGC表示对年老代进行并行收集。 | |
-XX:+UseParallelGC | 选择垃圾收集器为并行收集器。 | -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20,-XX:+UseParallelGC此配置仅对年轻代有效,即在示例配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。 |
-XX:+UseAdaptiveSizePolicy | 设置此选项后,并行收集器自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低响应时该间或者收集频率,该值建议使用并行收集器时,并且一直打开。 | -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy |
最佳实践
实践参数
java -Xms1024m -Xmx3072m -Xss256k -XX:MetaspaceSize=256m -XX:MaxDirectMemorySize=1g -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=1 -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/opt/app/logs/gc/${APP_NAME}-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=/opt/app/logs/javaHeapDump/dump2minio.sh -XX:HeapDumpPath=/opt/app/logs/javaHeapDump/dump.hprof -XX:ErrorFile=/opt/app/logs/crash/crash.txt -Dspring.profiles.active=$ENV_PROFILES_ACTIVE -javaagent:/opt/app/agent/skywalking-agent.jar -Dskywalking.agent.service_name=${APP_NAME}-${ENV} -Dskywalking.collector.backend_service=${SKYWALKING_SERVER_PORT} -javaagent:/opt/app/jvm-monitor/agent/jmx_prometheus_javaagent-0.15.0.jar=${JVM_MONITOR_PORT}:/opt/app/jvm-monitor/config/prometheus-jmx-config.yaml -jar /root/*.jar
参数说明
jvm参数 | 说明 | 调整思路 |
---|---|---|
-Xms1024m | 指定最小堆内存大小为1024m | 可调优,业务性能要求高,-Xms设置为-Xmx等值 |
-Xmx3072m | 指定最大堆内存大小为3072m | 可调优,设置为容器的75% |
-Xss300k | 指定每个线程的堆栈大小为300k | 可调优,具体看业务,一般256k也够了 |
-XX:MetaspaceSize=128m | 指定元空间大小为128m | 可调优,具体看业务,一般256M也够了 |
-XX:NewRatio=2 | 指定老年代和新生代比例,默认2 | 不清楚是否可删除,先不动 |
-XX:+UseConcMarkSweepGC | 设置年老代为并发收集 | 可调优,高吞吐的业务,用JDK8默认的GC更好,CMS有非常繁杂的参数,配置难度高,容易出错。在JDK14中移除了CMS,说明CMS不被社区认可。8G以上内存可以考虑低延迟的G1 |
-XX:CMSFullGCsBeforeCompaction=1 | 由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行1次GC以后对内存空间进行压缩、整理。 | 跟CMS搭配使用 |
-XX:CMSInitiatingOccupancyFraction=75 | 指在使用CMS收集器的情况下,老年代使用了指定阈值=75%的内存时,触发FullGC | 跟CMS搭配使用 |
-XX:+HeapDumpOnOutOfMemoryError | 当JVM发生OOM时,自动生成dump文件 | |
-XX:HeapDumpPath=/opt/app/logs/javaHeapDump/ | 指定dump文件的路径 | |
-javaagent:/opt/app/agent/skywalking-agent.jar | 附加了一个skywalking的agent | |
-Dskywalking.agent.service_name=${APP_NAME}-$ | 指定本服务在skywalking显示的服务名 | |
-Dskywalking.collector.backend_service=$ | 指定skywalking服务器url和端口 | |
-jar $ | 指定jar包路径 |
通过-XX:MaxRAMPercentage限制堆大小(推荐)
- 在容器环境下,Java只能获取服务器的配置,无法感知容器内存限制。您可以通过设置-Xmx来限制JVM堆大小,但该方式存在以下问题:
- 当规格大小调整后,需要重新设置堆大小参数。
- 当参数设置不合理时,会出现应用堆大小未达到阈值但容器OOM被强制关闭的情况。说明 应用程序出现OOM问题时,会触发Linux内核的OOM Killer机制。该机制能够监控占用过大内存,尤其是瞬间消耗大量内存的进程,然后它会强制关闭某项进程以腾出内存留给系统,避免系统立刻崩溃。
- 推荐的JVM参数设置。
-XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=70.0 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/admin/nas/gc-${POD_IP}-$(date '+%s').log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprof |
---|
参数说明如下。
参数 | 说明 |
---|---|
-XX:+UseContainerSupport | 使用容器内存。允许JVM从主机读取cgroup限制,例如可用的CPU和RAM,并进行相应的配置。当容器超过内存限制时,会抛出OOM异常,而不是强制关闭容器。 |
-XX:InitialRAMPercentage | 设置JVM使用容器内存的初始百分比。建议与-XX:MaxRAMPercentage保持一致,推荐设置为70.0。 |
-XX:MaxRAMPercentage | 设置JVM使用容器内存的最大百分比。由于存在系统组件开销,建议最大不超过75.0,推荐设置为70.0。 |
-XX:+PrintGCDetails | 输出GC详细信息。 |
-XX:+PrintGCDateStamps | 输出GC时间戳。日期形式,例如2019-12-24T21:53:59.234+0800。 |
-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date '+%s').log | GC日志文件路径。需保证Log文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录或收集到SLS,以便自动创建目录以及实现日志的持久化存储。 |
-XX:+HeapDumpOnOutOfMemoryError | JVM发生OOM时,自动生成DUMP文件。 |
-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprof | DUMP文件路径。需保证DUMP文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录,以便自动创建目录以及实现日志的持久化存储。 |
说明
- 使用-XX:+UseContainerSupport参数需JDK 8u191+、JDK 10及以上版本。
- JDK 11版本下日志相关的参数-XX:+PrintGCDetails、-XX:+PrintGCDateStamps、-Xloggc:$LOG_PATH/gc.log参数已废弃,请使用参数-Xlog:gc:$LOG_PATH/gc.log代替。
- Dragonwell 11暂不支持${POD_IP} 变量。
- 如果您没有将/home/admin/nas容器路径挂载到NAS目录,则必须保证该目录在应用启动前已存在,否则将不会产生日志文件。
通过-Xms -Xmx限制堆大小
- 您可以通过设置-Xms和-Xmx来限制堆大小,但该方式存在以下两个问题:
- 当规格大小调整后,需要重新设置堆大小参数。
- 当参数设置不合理时,会出现应用堆大小未达到阈值但容器OOM被强制关闭的情况。说明 应用程序出现OOM问题时,会触发Linux内核的OOM Killer机制。该机制能够监控占用过大内存,尤其是瞬间消耗大量内存的进程,然后它会强制关闭某项进程以腾出内存留给系统,避免系统立刻崩溃。
- 推荐的JVM参数设置。
-Xms2048m -Xmx2048m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/admin/nas/gc-${POD_IP}-$(date '+%s').log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprof |
---|
参数说明如下。
参数 | 说明 |
---|---|
-Xms | 设置JVM初始内存大小。建议与-Xmx相同,避免每次垃圾回收完成后JVM重新分配内存。 |
-Xmx | 设置JVM最大可用内存大小。为避免容器OOM,请为系统预留足够的内存大小。 |
-XX:+PrintGCDetails | 输出GC详细信息。 |
-XX:+PrintGCDateStamps | 输出GC时间戳。日期形式,例如2019-12-24T21:53:59.234+0800。 |
-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date '+%s').log | GC日志文件路径。需保证Log文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录或收集到SLS,以便自动创建目录以及实现日志的持久化存储。 |
-XX:+HeapDumpOnOutOfMemoryError | JVM发生OOM时,自动生成DUMP文件。 |
-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprof | DUMP文件路径。需保证DUMP文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录,以便自动创建目录以及实现日志的持久化存储。 |
- 推荐的堆大小设置。
内存规格大小 | JVM堆大小 |
---|---|
1 GB | 600 MB |
2 GB | 1434 MB |
4 GB | 2867 MB |
8 GB | 5734 MB |
总结
1、制定统一规范,为业务稳定带来保障
2、规范的同时,最大限度提高生产效率