OS内核参数和JVM参数的调整

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OS内核参数和JVM参数的调整相关的知识,希望对你有一定的参考价值。

参考技术A OS内核参数调整

vm.overcommit_memory  内存分配策略:可选值:0,1,2

0:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

2: 表示内核允许分配超过所有物理内存和交换空间总和的内存。

一般需要将这个参数的值调整为1

可以用如下命令修改: echo 'vm.overcommit_memory=1'>> /etc/sysctl.conf

vm.max_map_count  文件句柄数

这个参数的值会影响中间件系统可以开启的线程的数量。

如果这个参数过小,有的时候可能会导致有些中间件无法开启足够的线程,进而导致报错,甚至中间件系统挂掉。

可以用如下命令修改: echo 'vm.max map_ count=655360' >> /etc/sysctl.conf.

vm.swappiness  控制换出运行时内存的相对权重

os会把一部分磁盘空间作为swap区域,然后如果有的进程现在可能不太活跃,就会被操作系统把进程调整为睡眠状态,把进程中的数据放入磁盘上的swap区域,然后这个进程把原来占用的内存空间腾出来,交给其他活跃运行的进程来使用。

如果这个参数的值设置为0,意思就是尽量别把任何一个进程放到磁盘swap区域去,尽量大家都用物理内存。

如果这个参数的值是100,那么意思就是尽量把一些进程给放到磁盘swap区域去,内存腾出来给活跃的进程使用。

默认这个参数的值是60,有点偏高了,可能会导致我们的中间件运行不活跃的时候被迫腾出内存空间然后放磁盘swap区域去。

因此通常在生产环境建议把这个参数调整小-些,比如设置为10,尽量用物理内存,别放磁盘swap区域去。

可以用如下命令修改: echo 'vm.swappiness=10' >> /etc/sysctl.conf。

ulimit

这个是用来控制inux上的最大文件链接数的,默认值可能是1024, 一般肯定是不够的,因为你在大量频繁的读写磁盘文件的时候,或者是进行网络通信的时候,都会跟这个参数有关系对于一个中间件系统而言肯定是不能使用默认值的,如果你采用默认值,很可能在线上会出现如下错误: error: too many open files。

因此通常建议用如下命令修改这个值: echo 'ulimit -n 1000000' >> /etc/profile.

总结:

实大家综合思考一下这几个参数, 会发现到最后要调整的东西,无非都是跟磁盘文件IO、网络通信、内存管理、线程数量有关系的,因为我们的中间件系统在运行的时候无非就是跟这些打交道。

●中间件系统肯定要开启大量的线程(跟vm.max_map_count有关)

●而且要进行大量的网络通信和磁盘IO (跟ulimit有关)

●然后大量的使用内存(跟vm.swappiness和vm.overcommit_memory有关)

所以对OS内核参数的调整,往往也就是围绕跟中间件 系统运行最相关的一东西。

JVM参数调整

-server :这个参数就是说用服务器模式启动,这个没什么可说的,现在一般都是如此。

-Xms8g -Xmx8g -Xmn4g :这个就是很关键的一块参数了,也是重点需要调整的,就是默认的堆大小是8g内存,新生代是4g内存,但是我们的高配物理机是48g内存的,所以这里完全可以给他们翻几倍,比如给堆内存20g,中新生代给10g,甚至可更多-些,当然要留一些内存给操作系统来用。

-XX:+UseG1GC -XX:G1HeapRegionSize=16m :这几个参数也是至关重要的,这是选用了G1垃圾回收器来做分代回收,对新生代和老年代都是用G1来回收这里把G1的region大小设置为了16m,这个因为机器内存比较多,所以region大小可以调大-些给到16m, 不然用2m的region, 会

导致region数量过多的。

-XX:G1 ReservePercent=25 :这个参数是说,在G1管理的老年代里预留25%的空闲内存,保证新生代对象晋升到老年代的时候有足够空间,避免老年代内存都满了,新生代有对象要进入老年代没有充足内存了默认值是10%,略微偏少,这里RocketMQ给调大了一些。

-XX:InitiatingHeapOccupancyPercent=30 :这个参数是说,当堆内存的使用率达到30%之后就会自动启动G1的并发垃圾回收,开始尝试回收一些垃圾对象,默认值是45%,这里调低了一些,也就是提高了GC的频率,但是避免了垃圾对象过多, 一次垃圾回收耗时过长的问题。

-XX:SoftRefLRUPolicyMSPerMB=0 :这个参数不要设置为0,避免频繁回收-些软引|用的Class对象,这里可以调整为比如1000。

-verbose:gc -Xloggc:/dev/shm/mq_ gc _%p.log -XX:+ PrintGCDetails -XX: + PrintGCDateStamps -XX: + PrintGCApplicationStoppedTime -XX:+ PrintAdaptiveSizePolicy -XX:+UseGCLogFileRotation -

XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m :这一堆参数都是控制GC日志打印输出的, 确定了gc日志文件的地址,要打印哪些详细信息,然后控制每个gc日志文件的大小是30m,最多保留5个gc日志文件。

-XX:-OmitStackTraceInFastThrow :这个参数是说,有时候JVM会抛弃-些异常堆栈信息, 因此这个参数设置之后,就是禁用这个特性,要把完整的异常堆栈信息打印出来。

-XX:+ AlwaysPreTouch :这个参数的意思是我们刚开始指定JVM用多少内存,不会真正分配给他,会在实际需要使用的时候再分配给他。

所以使用这个参数之后,就是强制让VM启动的时候直接分配我们指定的内存,不要等到使用内存的时候再分配。

-XX:MaxDirectMemorySize= 15g :这是说RocketMQ里大用了NIO中的direct buffer,这里限定了direct buffer最多申请多少,如果你机器内存比较大,可以适当调大这个值。

-XX:-UseLargePages -XX:-UseBiasedLocking :这两个参数的意思是禁用大内存页和偏向锁。

RocketMQ核心参数调整

sendMessageThreadPoolNums

RocketMQ内部用来发送消息的线程池的线程数量,默认是16。这个参数可以根据你的机器的CPU核数进行适当增加。

Day312.RocketMQ集群进行OS内核&JVM参数的调整 -RocketMQ

RocketMQ集群进行OS内存&JVM参数的调整

为了让RokcetMQ发挥最佳的性能,对OS内核&JVM参参数进行优化调整

因为RokcetMQ由Java代码编写,那么JVM的底层的内核参数,会直接影响RokcetMQ的性能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CgCll5Pi-1624859980495)(C:\\Users\\Administrator\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210628110053933.png)]

一、对OS内核参数进行调整

1、vm.overcommit_memory

os内核内存分配策略

  • 填写值:

    • 0:表示内核将检查是否有足够的可用内存供应用进程使用;
      • 如果内存足够的话就分配内存给你
      • 如果感觉剩余内存不足,就拒绝你的申请,导致你申请内存失败,进而导致中间件系统异常出错
    • 1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
      • 所有可用的物理内存都允许分配给你,只要有内存就给你来用,这样可以避免申请内 存失败的问题
    • 2:表示内核允许分配超过所有物理内存和交换空间总和的内存
  • 设置指令:

通过设置:1,来保证中间件在获取内存时不会因为内存不足,而拒绝报错

echo 'vm.overcommit_memory=1' >> /etc/sysctl.conf。

2、vm.max_map_count

这个参数的值会影响中间件系统可以开启的线程的数量

  • 参数过小,有的时候可能会导致有些中间件无法开启足够的线程,进而导致报错,甚至中间件系统挂掉
  • 默认值是65536
  • 建议可以把这个参数调大10倍比如655360这样的值,保证中间件可以开启足够多的线程。
  • 设置指令:
echo 'vm.max_map_count=655360' >> /etc/sysctl.conf

3、vm.swappiness

控制进程的swap行为

swap区域理解为睡眠区,在这里不会占用内存

就是os会把一部分磁盘空间作为swap区域,然后如果有的进程现在可能不是太活跃,就会被操作系统把进程调整为睡眠状态,把进程中的数据放入磁盘上的swap区域,然后让这个进程把原来占用的内存空间腾出来,交给其他活跃运行的进程来使用。

  • 如果这个参数的值设置为 0,就是尽量不把任何一个进程放到磁盘swap区域去,尽量都使用物理内存

  • 如果这个参数的值是 100,那么意思就是尽量放到磁盘swap区域去,内存腾出来给活跃的进程使用。

  • 默认这个参数的值是 60,有点偏高,可能会导致我们的中间件运行不活跃的时候被迫腾出内存空间然后放磁盘swap区域去。

  • 因此通常在生产环境建议把这个参数调整小一些,比如设置为10,尽量用物理内存,别放磁盘swap区域去。

  • 设置指令:

echo 'vm.swappiness=10' >> /etc/sysctl.conf

4、ulimit

控制linux上的最大文件链接数

  • 默认值可能是1024

  • 如果你在大量频繁的读写磁盘文件的时候,或者是进行网络通信的时候,都会跟这个参数有关系

  • 对于一个中间件系统而言肯定是不能使用默认值

  • 如果你采用默认值,很可能在线上会出现如下错误:error: too many openfiles

  • 设置指令:

echo 'ulimit -n 1000000' >> /etc/profile

5、总结

其实大家综合思考一下这几个参数,会发现到最后要调整的东西,无非都是跟磁盘文件IO、网络通信、内存管理、线程数量有关系的 ,因为我们的中间件系统在运行的时候无非就是跟这些打交道。

  • 中间件系统肯定要开启大量的线程(跟vm.max_map_count有关

  • 而且要进行大量的网络通信和磁盘IO(跟ulimit有关

  • 然后大量的使用内存(跟vm.swappiness和vm.overcommit_memory有关

所以对OS内核参数的调整,往往也就是围绕跟中间件系统运行最相关的一些东西。


二、对JVM参数进行调整

1、参数设置

在rocketmq/distribution/target/apache-rocketmq/bin目录下,就有对应的启动脚本,比如mqbroker是用来启动Broker的,mqnamesvr是用来启动NameServer的。↓↓↓

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HM5FFz6D-1624859980498)(C:\\Users\\Administrator\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210628120330170.png)]

用mqbroker来举例,我们查看这个脚本里的内容,最后有如下一行:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQ7q2otk-1624859980500)(C:\\Users\\Administrator\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210628120800519.png)]

sh ${ROCKETMQ_HOME}/bin/runbroker.sh org.apache.rocketmq.broker.BrokerStartup $@

这一行内容就是用runbroker.sh脚本来启动一个JVM进程,JVM进程刚开始执行的main类就是
org.apache.rocketmq.broker.BrokerStartup
我们接着看runbroker.sh脚本,在里面可以看到如下内容:

JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"
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:/dev/shm/mq_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy"
JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"
#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}"

在上面的内容中,其实就是在为启动Broker设置对应的JVM参数和其他一些参数,我们可以把其中JVM相关的参数抽取出来给大家解释一下:

  • -server:这个参数就是说用服务器模式启动,这个没什么可说的,现在一般都是如此

  • -Xms8g -Xmx8g -Xmn4g:这个就是很关键的一块参数了,也是重点需要调整的,就是默认的堆大小是8g内存,新生代是4g内存,但是如果高配物理机是48g内存的,所以这里完全可以给他们翻几倍,比如给堆内存20g,其中新生代给10g,甚至可以更多一些,当然要留一些内存给操作系统来用

  • -XX:+UseG1GC -XX:G1HeapRegionSize=16m:这几个参数也是至关重要的,这是选用了G1垃圾回收器来做分代回收,对新生代和老年代都是用G1来回收这里把G1的region大小设置为了16m,这个因为机器内存比较多,所以region大小可以调大一些给到16m,不然用2m的region,会导致region数量过多的

  • -XX:G1ReservePercent=25:这个参数是说,在G1管理的老年代里预留25%的空闲内存,保证新生代对象晋升到老年代的时候有足够空间,避免老年代内存都满了,新生代有对象要进入老年代没有充足内存了
    默认值是10%,略微偏少,这里RocketMQ给调大了一些

  • -XX:InitiatingHeapOccupancyPercent=30:这个参数是说,当堆内存的使用率达到30%之后就会自动启动G1的并发垃圾回收,开始尝试回收一些垃圾对象
    默认值是45%,这里调低了一些,也就是提高了GC的频率,但是避免了垃圾对象过多,一次垃圾回收耗时过长的问题

  • -XX:SoftRefLRUPolicyMSPerMB=0:这个参数默认设置为0了,其实建议这个参数不要设置为0,避免频繁回收一些软引用的Class对象,这里可以调整为比如1000

  • -verbose:gc -Xloggc:/dev/shm/mq_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -
    XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -XX:+UseGCLogFileRotation -
    XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m:这一堆参数都是控制GC日志打印输出的,确定了gc日志文件的地址,要打印哪些详细信息,然后控制每个gc日志文件的大小是30m,最多保留5个gc日志文件。

  • -XX:-OmitStackTraceInFastThrow:这个参数是说,有时候JVM会抛弃一些异常堆栈信息,因此这个参数设置之后,就是禁用这个特性,要把完整的异常堆栈信息打印出来

  • -XX:+AlwaysPreTouch:这个参数的意思是我们刚开始指定JVM用多少内存,不会真正分配给他,会在实际需要使用的时候再分配给他,懒分配是否开启
    所以使用这个参数之后,就是强制让JVM启动的时候直接分配我们指定的内存,不要等到使用内存的时候再分配

  • -XX:MaxDirectMemorySize=15g:这是说RocketMQ里大量用了NIO中的direct buffer,这里限定了direct buffer最多申请多少,如果你机器内存比较大,可以适当调大这个值

  • -XX:-UseLargePages -XX:、-UseBiasedLocking:这两个参数的意思是禁用大内存页和偏向锁,这两个参数对应的概念每个要说清楚都得一篇文章,所以这里大家直接知道人家禁用了两个特性即可。

2、总结

RocketMQ默认的JVM参数是采用G1垃圾回收器,默认堆内存大小是8G
这个其实完全可以根据自己使用的机器内存来调整,你可以增大一些也是没有问题的,然后就是一些G1的垃圾回收的行为参数做了调整, 这个一般我们不用去动,然后就是对GC日志打印做了设置,这个一般也不用动。

其余的就是禁用一些特性,开启一些特性,这些都直接维持RocketMQ的默认值即可。

三、对RokcetMQ核心参数进行调整

在下面的目录里有dledger的示例配置文件:rocketmq/distribution/target/apache-rocketmq/conf/dledger

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lr8UO0QG-1624859980501)(C:\\Users\\Administrator\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210628135415488.png)]

  • sendMessageThreadPoolNums=16

RocketMQ内部用来发送消息的线程池的线程数量,默认是16;

可以根据你的机器的CPU核数进行适当增加,比如机器CPU是24核的,可以增加这个线程数量到24或者30,都是可以的。

四、总结

(1)中间件系统在压测或者上生产之前,需要对三大块参数进行调整:

  • OS内核参数
  • JVM参数
  • 中间件核心参数

(2)OS内核参数主要调整的地方都是跟磁盘IO、网络通信、内存管理以及线程管理有关的,需要适当调节大小
(3)JVM参数需要我们去中间件系统的启动脚本中寻找他的默认JVM参数,然后根据机器的情况,对JVM的堆内存大小,新生代大小,Direct Buffer大小,等等,做出一些调整,发挥机器的资源
(4)中间件核心参数主要也是关注其中跟网络通信、磁盘IO、线程数量、内存 管理相关的,根据机器资源,适当可以增加网络通信线程,控制同步刷磁盘或者异步刷磁盘,线程数量有多少,内存中一些队列的大小

以上是关于OS内核参数和JVM参数的调整的主要内容,如果未能解决你的问题,请参考以下文章

linux 内核参数优化

在 R 中调整 svm 参数(线性 SVM 内核)

Linux 系统调整内核参数

nginx性能优化及内核参数调整

内核参数列表

内核参数列表