RocketMQ部署之动态设置JVM启动参数
这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党
背景
线上的RocketMQ
集群有运行一段时间了。比如测试环境和线上环境的RocketMQ
集群部署的机器内存大小肯定不一样。所以可能要写多个部署脚本。非常麻烦
官方的部署脚本是不支持根据宿主机内存大小动态设置JVM启动参数的
可以看到是写死的,给4g。
但是比如我线上的机器内存大小为8g,实际我要给的内存可能是6g。我又需要手动改脚本非常麻烦。所以想要修改基于宿主机内存大小自动调节JVM内存大小
基于jvm自带参数
实际上jdk在11就支持动态参数了,比如上面的脚本我们可以改成如下方式
choose_gc_options()
{# Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...# '1' means releases befor Java 9JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | sed -r -n 's/.* version "([0-9]*).*$/\1/p')if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; thenJAVA_OPT="${JAVA_OPT} -server -XX:MaxRAMPercentage=70 -XX:MinRAMPercentage=70 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"elseJAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"fi
}
-XX:MaxRAMPercentage
用于设置JVM可使用的最大RAM百分比。举例来说,你可以使用-XX:MaxRAMPercentage=75
指定JVM最多可用服务器内存的75%。
但是实际启动会报错,当前的服务器jdk版本不支持
我的jdk版本为1.8.0_362
实际我们是可以改动RocketMQ
源码去支持jdk11的部署,但是这种方式比较耗费精力。所以我这里决定使用sh脚本来实现
sh脚本实现
核心脚本代码主要是这几行
# 获取宿主机内存总量(单位:M)
total_mem=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024)}')# 将内存总量转为单位:G 向上取整
mem_in_g=$((total_mem + 1023 / 1024))# 判断内存大小,按需设定内存分配比例
if [ $mem_in_g -lt 16 ]; thenmem_ratio=90
elif [ $mem_in_g -ge 16 -a $mem_in_g -lt 32 ]; thenmem_ratio=95
elif [ $mem_in_g -ge 32 ]; thenmem_ratio=95
fiheap_size=$(($total_mem * $mem_ratio /100 / 1024))
metaspace_size=$(echo "$total_mem * 0.02" | bc | awk '{print int($1+0.5)}' | sed -e 's/^0\{1,\}//')
max_metaspace_size=$(echo "$total_mem * 0.04" | bc | awk '{print int($1+0.5)}' | sed -e 's/^0\{1,\}//')choose_gc_options()
{# Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...# '1' means releases befor Java 9JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | sed -r -n 's/.* version "([0-9]*).*$/\1/p')if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; thenJAVA_OPT="${JAVA_OPT} -server -Xms${heap_size}g -Xmx${heap_size}g -XX:MetaspaceSize=${metaspace_size}m -XX:MaxMetaspaceSize=${max_metaspace_size}m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"elseJAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"fi
}
上面的脚本都有注释。我们大致还是解释下
- 获取宿主机的内存大小(非可用内存,我们要保证宿主机分配不到预定内存就启动报错)
- 小于16g内存给总内存的90%
- 大于等于16g小于32g内存我们给总内存的95%
- 大于等于32g的我们也给95%内存(实际这里可以和判断3一起,但是为了以后可能调整分配的内存大小就暂时分开)
- 元空间大小我们给总内存的0.02
- 最大元空间大小我们给总内存的0。04
- 注意获取到的总内存要向上取整,因为8g的机器我们实际获取到的内存大小大概为7296M,我们加一个1023(一个无线趋近于1的数就可以向上取整了)
最后给一个完整的runserver.sh
runserver.sh
#!/bin/sh# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.#===========================================================================================
# Java Environment Setting
#===========================================================================================
error_exit ()
{echo "ERROR: $1 !!"exit 1
}find_java_home()
{case "`uname`" inDarwin)JAVA_HOME=$(/usr/libexec/java_home);;*)JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac))));;esac
}find_java_home[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
[ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!"export JAVA_HOME
export JAVA="$JAVA_HOME/bin/java"
export BASE_DIR=$(dirname $0)/..
export CLASSPATH=.:${BASE_DIR}/conf:${BASE_DIR}/lib/*:${CLASSPATH}#===========================================================================================
# JVM Configuration
#===========================================================================================
# The RAMDisk initializing size in MB on Darwin OS for gc-log
DIR_SIZE_IN_MB=600# 获取宿主机内存总量(单位:M)
total_mem=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024)}')# 将内存总量转为单位:G 向上取整
mem_in_g=$((total_mem + 1023 / 1024))# 判断内存大小,按需设定内存分配比例
if [ $mem_in_g -lt 16 ]; thenmem_ratio=90
elif [ $mem_in_g -ge 16 -a $mem_in_g -lt 32 ]; thenmem_ratio=95
elif [ $mem_in_g -ge 32 ]; thenmem_ratio=95
fiheap_size=$(($total_mem * $mem_ratio /100 / 1024))
metaspace_size=$(echo "$total_mem * 0.02" | bc | awk '{print int($1+0.5)}' | sed -e 's/^0\{1,\}//')
max_metaspace_size=$(echo "$total_mem * 0.04" | bc | awk '{print int($1+0.5)}' | sed -e 's/^0\{1,\}//')choose_gc_log_directory()
{case "`uname`" inDarwin)if [ ! -d "/Volumes/RAMDisk" ]; then# create ram disk on Darwin systems as gc-log directoryDEV=`hdiutil attach -nomount ram://$((2 * 1024 * DIR_SIZE_IN_MB))` > /dev/nulldiskutil eraseVolume HFS+ RAMDisk ${DEV} > /dev/nullecho "Create RAMDisk /Volumes/RAMDisk for gc logging on Darwin OS."fiGC_LOG_DIR="/Volumes/RAMDisk";;*)# check if /dev/shm exists on other systemsif [ -d "/dev/shm" ]; thenGC_LOG_DIR="/dev/shm"elseGC_LOG_DIR=${BASE_DIR}fi;;esac
}choose_gc_options()
{# Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...# '1' means releases befor Java 9JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | sed -r -n 's/.* version "([0-9]*).*$/\1/p')if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; thenJAVA_OPT="${JAVA_OPT} -server -Xms${heap_size}g -Xmx${heap_size}g -XX:MetaspaceSize=${metaspace_size}m -XX:MaxMetaspaceSize=${max_metaspace_size}m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"elseJAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"fi
}choose_gc_log_directory
choose_gc_options
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
#JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"$JAVA ${JAVA_OPT} $@
RocketMQ部署之动态设置JVM启动参数相关推荐
- 使用-XX:+PrintCommandLineFlags展示JVM启动参数
导语: 近期在学习周志明老师的<<深入理解Java虚拟机: JVM高级特性与最佳实践(第3版)>>, 在IDEA中测试老师的示例代码时, 发现程序的输出和老师的输出不一样, 想 ...
- JVM 启动参数详解:博观而约取、厚积而薄发
JVM 作为一个通用的虚拟机,我们可以通过启动 Java 命令时指定不同的 JVM 参数,让 JVM 调整自己的运行状态和行为,内存管理和垃圾回收的 GC 算法,添加和处理调试和诊断信息等等.本节概括 ...
- JVM 启动参数详解
JVM 启动参数详解 JVM 作为一个通用的虚拟机,我们可以通过启动Java命令时指定不同JVM参数,让 JVM调整自己的运行状态和行为,内存管理和垃圾回收的GC算法等等. 直接通过命令行启动 Jav ...
- 全网最硬核 JVM TLAB 分析 3. JVM EMA期望算法与TLAB相关JVM启动参数
今天,又是干货满满的一天.这是全网最硬核 JVM 系列的开篇,首先从 TLAB 开始.由于文章很长,每个人阅读习惯不同,所以特此拆成单篇版和多篇版 全网最硬核 JVM TLAB 分析(单篇版不包含额外 ...
- JVM启动参数解析(转)
JVM启动参数解析(转) (2010-03-17 19:45:19) 转载 标签: jvm 启动参数 it 分类:他山之石攻己之玉 dk1.4.2 JVM官方地址:http://java.sun.co ...
- 【Java 虚拟机原理】垃圾回收算法 ( 设置 JVM 命令参数输出 GC 日志 | GC 日志输出示例 | GC 日志分析 )
文章目录 一.设置 JVM 命令参数输出 GC 日志 二.GC 日志示例 三.GC 日志分析 一.设置 JVM 命令参数输出 GC 日志 在 IntelliJ IDEA 的启动参数中设置 -XX:+P ...
- 不需要再手工指定JVM启动参数-XX:+UseCompressedOops
技术团队通过 GCeasy 工具分析完几千次用户上传的GC日志后, 发现一个现象: 仍然有很多Java程序传入了JVM启动参数 -XX:+UseCompressedOops. 实际上,如果JVM的版本 ...
- JVM启动参数详解(含调优)
java启动参数共分为三类: 其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足, ...
- JVM启动参数配置详解
JVM启动参数配置详解 1. JDK8的JVM启动参数默认配置 2. JDK8的JVM启动参数说明 2.1 基本参数 2.2 G1相关参数 2.3 辅助信息 1. JDK8的JVM启动参数默认配置 - ...
最新文章
- ORACLE告警日志文件
- Linux编程之定制带级别的log
- Central Authentication Service
- 【QGIS入门实战精品教程】3.1:QGIS如何连接SQL Server数据库?
- 英特尔FPGA技术大会: 加快塑造边缘、网络和云端的未来
- 浙江大学计算机科学与技术博士培养研究方向,浙江大学计算机科学技术学院博士研究生导师简介:王跃明...
- PHPnow中ZendDebugger与ZendOptimizer 共存
- Keil 5安装教程
- ADB常用命令--测试人员必备
- 云计算十字真言及其在小博无线的实践
- 如何查看我的订单-REST的流程API设计案例
- 计算机英语词汇合成词有哪些,2018年12月英语四级词汇讲解丨考点归纳:合成词...
- C++ SuperLU 混合编程
- 城市生活污水处理技术现状及活性炭的应用
- 使用DISM启用或禁用Windows功能
- PCB中solder层和paste层的区别
- 苹果11怎样设置自动锁屏 iPhone11自动锁屏操作方法
- 使用lucene的多字段排序--回复网友BUFFON
- JavaScript限时秒杀
- 12种高效的管理方法