RocketMQ是一款优秀的消息中间件,从它的启动脚本配置中可以学习到os参数优化的一些思路和经验。但是也不能直接照搬,需要理解其中的参数详解,对比当前项目场景是否适用。用的时候也需要进行多方测试,以免出现问题,千万不要瞎优化。
RocketMQ为了实现高性能高吞吐,对一些参数的调整比较激进。RocketMQ的部署建议是最好在物理实体机上,该机器上不要部署其他同样需要大量资源的软件。
2 从os.sh脚本看参数优化os.sh脚本位置在 https://github.com/apache/rocketmq/blob/master/distribution/bin/os.sh
该脚本建议一些优化的参数如下:
sudo sysctl -w vm.overcommit_memory=1
sudo sysctl -w vm.drop_caches=1
sudo sysctl -w vm.zone_reclaim_mode=0
sudo sysctl -w vm.max_map_count=655360
sudo sysctl -w vm.dirty_background_ratio=50
sudo sysctl -w vm.dirty_ratio=50
sudo sysctl -w vm.dirty_writeback_centisecs=360000
sudo sysctl -w vm.page-cluster=3
sudo sysctl -w vm.swappiness=1
echo 'ulimit -n 655350' >> /etc/profile
echo '* hard nofile 655350' >> /etc/security/limits.conf
echo '* hard memlock unlimited' >> /etc/security/limits.conf
echo '* soft memlock unlimited' >> /etc/security/limits.conf
DISK=`df -k | sort -n -r -k 2 | awk -F/ 'NR==1 {gsub(/[0-9].*/,"",$3); print $3}'`
[ "$DISK" = 'cciss' ] && DISK='cciss!c0d0'
echo 'deadline' > /sys/block/${DISK}/queue/scheduler
linux vm参数的含义可以在 https://sysctl-explorer.net/vm/ 上找到相应解释。有些参数不好用中文描述,需要沿用英文解释。有些参数使用案例资料太少,只能找一些解释参考下
2.1 vm.overcommit_memory=1可选值:0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
将这个参数的值调整为1,意思是把所有可用的物理内存都允许分配给你,只要有内存就给你来用,这样可以避免申请内存失败的问题
0:开启缓存机制
1:清空页缓存
2:清空inode和目录树缓存
3:清空所有缓存
大多数GNU Linux都是默认开启了缓存机制的,查看配置文件 cat /proc/sys/vm/drop_caches 若为0的话,则表示开启了缓存机制的,这种机制在一直运行某个服务的时候非常有效,便于服务本身的快速读取,而作为桌面用户来说,打开的程序并不那么单一,所以桌面用户还是建议设置此配置文件为1,及时对系统缓存进行清理,释放空间以供其它程序使用
2.3 vm.zone_reclaim_mode=0Zone_reclaim_mode allows someone to set more or less aggressive approaches to reclaim memory when a zone runs out of memory. If it is set to zero then no zone reclaim occurs Allocations will be satisfied from other zones / nodes in the system.
This is value ORed together of
1 = Zone reclaim on
2 = Zone reclaim writes dirty pages out
4 = Zone reclaim swaps pages
如果将其设置为零,则不会发生区域回收。
该参数和cpu的NUMA架构有关。
简单点说,NUMA(Non-Uniform Memory Access)是对UMA(Uniform Memory Access)架构的优化。
UMA: 每个CPU核共享相同的内存地址空间。但随着CPU核心数的增加,架构会遇到问题,比如对总线的带宽带来挑战、访问同一块内存的冲突问题。
NUMA: 不同的内存和CPU核从属不同的 Node,每个 Node 都有自己的集成内存控制器(IMC,Integrated Memory Controller)。在 Node 内部,架构类似SMP,使用 IMC Bus 进行不同核心间的通信;不同的 Node 间通过QPI(Quick Path Interconnect)进行通信.有点多级Bus的意味。
NUMA参考:https://www.jianshu.com/p/0607c5f62c51
zone_reclaim_mode详细解释参考: https://sysctl-explorer.net/vm/zone_reclaim_mode/
通俗点讲,该参数表示可以开启的线程的数量。如果这个参数过小,可能会导致中间件无法开启足够的线程,进而导致报错。默认值是65536,但是这个值是不够的,需要把这个参数调大
2.5 vm.dirty_background_ratio=50 2.6 vm.dirty_ratio=50 2.7 vm.dirty_writeback_centisecs=360000以上3个参数都是与脏页缓存相关的。参考此文章描述:https://feichashao.com/dirty_ratio_and_dirty_background_ratio/
vm.dirty_background_ratio: 是内存可以填充“脏数据”的百分比。这些“脏数据”在稍后是会写入磁盘的,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。举一个例子,我有32G内存,那么有3.2G的内存可以待着内存里,超过3.2G的话就会有后来进程来清理它。
vm.dirty_ratio: 是绝对的脏数据限制,内存里的脏数据百分比不能超过这个值。如果脏数据超过这个数量,新的IO请求将会被阻挡,直到脏数据被写进磁盘。这是造成IO卡顿的重要原因,但这也是保证内存中不会存在过量脏数据的保护机制。
vm.dirty_writeback_centisecs: 指定多长时间 pdflush/flush/kdmflush 这些进程会起来一次
2.8 vm.page-cluster=3page-cluster是用来控制从swap空间换入数据的时候,一次连续读取的页数,这相当于对交换空间的预读。这里的连续是指在swap空间上的连续,而不是在内存地址上的连续。因为swap空间一般是在硬盘上,对硬盘设备的连续读取将减少磁头的寻址,提高读取效率。这个文件中设置的值是2的指数。就是说,如果设置为0,预读的swap页数是2的0次方,等于1页。如果设置为3,就是2的3次方,等于8页。同时,设置为0也意味着关闭预读功能
2.9 vm.swappiness=1swappiness的值的大小对如何使用swap分区是有着很大的联系的。swappiness=0的时候表示最大限度使用物理内存,然后才是 swap空间,swappiness=100的时候表示积极的使用swap分区,并且把内存上的数据及时的搬运到swap空间里面。
从性能上来说,当然越小性能越好,但是也不能小到等于0,0表示别把任何一个进程放到磁盘swap区域去,可能会造成系统崩溃。
echo ‘ulimit -n 655350’ >> /etc/profile
echo ‘* hard nofile 655350’ >> /etc/security/limits.conf
echo ‘* hard memlock unlimited’ >> /etc/security/limits.conf
echo ‘* soft memlock unlimited’ >> /etc/security/limits.conf
如果不调大这些参数,会遇到too many open files之类的错误,相信部署过elasticsearch等中间件的小伙伴对这种报错信息不会陌生。
ps:
ulimit -n 655350 调大每个进程默认打开的最大文件句柄数
memlock 最大锁定内存地址空间
DISK=`df -k | sort -n -r -k 2 | awk -F/ 'NR==1 {gsub(/[0-9].*/,"",$3); print $3}'`
[ "$DISK" = 'cciss' ] && DISK='cciss!c0d0'
echo 'deadline' > /sys/block/${DISK}/queue/scheduler
脚本含义: 遍历所有磁盘,找到符合条件的磁盘,对其使用deadline调度策略
对于磁盘I/O,Linux提供了cfq, deadline和noop三种调度策略
cfq: 这个名字是Complete Fairness Queueing的缩写,它是一个复杂的调度策略,按进程创建多个队列,试图保持对多个进程的公平(这就没考虑读操作和写操作的不同耗时)
deadline: 这个策略比较简单,只分了读和写两个队列(这显然会加速读取量比较大的系统),叫这个名字是内核为每个I/O操作都给出了一个超时时间
noop: 这个策略最简单,只有单个队列,只有一些简单合并操作
考虑到硬件配置、实际应用场景(读写比例、顺序还是随机读写)的差异,上面的简单解释对于实际选择没有太大帮助,实际该选择哪个基本还是要实测来验证。不过下面几条说明供参考:
根据多篇文章的说法,deadline和noop差异不是太大,但它们俩与cfq差异就比较大。
参考资料: https://www.cnblogs.com/bamanzi/p/linux-disk-io-scheduler.html
由于并不是专业的linux运维,有些参数网上资料较少,讲的也比较模糊,先做个记录,有时间再找资料研究下参数的含义和使用场景。不过我们从中可以学习到os内核参数优化的大体思路。学习总结,有时候需要抓大放小
欢迎关注我的微信公众号: wanjinyu的技术小窝