Skip to content
文章目录

背景

目前本公司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').logGC日志文件路径。需保证Log文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录或收集到SLS,以便自动创建目录以及实现日志的持久化存储。
-XX:+HeapDumpOnOutOfMemoryErrorJVM发生OOM时,自动生成DUMP文件。
-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprofDUMP文件路径。需保证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').logGC日志文件路径。需保证Log文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录或收集到SLS,以便自动创建目录以及实现日志的持久化存储。
-XX:+HeapDumpOnOutOfMemoryErrorJVM发生OOM时,自动生成DUMP文件。
-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date '+%s').hprofDUMP文件路径。需保证DUMP文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录,以便自动创建目录以及实现日志的持久化存储。
  • 推荐的堆大小设置。
内存规格大小JVM堆大小
1 GB600 MB
2 GB1434 MB
4 GB2867 MB
8 GB5734 MB

总结

1、制定统一规范,为业务稳定带来保障

2、规范的同时,最大限度提高生产效率