问题描述
在2020-03-16 18:00左右收到告警,业务出现发送RocketMQ失败,在约1分钟左右后自动恢复。RocketMQ运行向来稳定,为何也抖动了?
Broker日志分析
查看GC日志
通过查看发时间问题时间附近GC日志并无发现异常。
1 | 2020-03-16T17:49:13.785+0800: 13484510.599: Total time for which application threads were stopped: 0.0072354 seconds, Stopping threads took: 0.0001536 seconds |
查看Broker日志
由日志可以看出:slave与问题节点broker同步信息异常。
1 | 2020-03-16 17:55:15 ERROR BrokerControllerScheduledThread1 - SyncTopicConfig Exception, x.x.x.x:10911 |
1 | 备注:通过查看RocketMQ的集群和GC日志,只能说明但是网络不可用,造成主从同步问题;并未发现Broker自身出问题了。 |
系统监控分析
网络监控
网络ping在问题时间段发送中断,网络没有流量。
磁盘IO监控
在问题时间段磁盘IO有陡增
CPU监控
CPU在问题时间段有飙高后回落
内存信息
内存信息没有采集到,由于当时网络中断了。
集群流量
除了网络终端未采集到数据外,问题时间断之前只有6000左右的TPS;网络恢复后有个脉冲到11301,然而总体负载很低。
1 | 2020-03-16T17:54:05.037+08:00 bike_mq totalTps 6576 |
1 | 备注:通过监控看到在问题时间段网络、CPU、磁盘IO都出现了问题;到底是磁盘IO引起CPU飙高的?进而影响网络的;还是CPU先飙高引起网络中断和磁盘IO的。机器上只有一个RocketMQ进程,而且当时流量负载并不高;所以由应用进程导致CPU、网络、磁盘IO等问题是解释不通的。那会不会阿里云抖动呢?但是如果阿里云抖动为何只影响RocketMQ集群的3个节点呢?其他RocketMQ集群没有问题;业务机器也没有发现网络等问题。 |
Linux系统日志分析
通过查看问题时间段日志,发现页分配失败“page allocation failure. order:0, mode:0x20”,也就Page不够了。
1 | 2020-03-16T17:56:07.505715+08:00 VECS0xxxx kernel: <IRQ> [<ffffffff81143c31>] ? __alloc_pages_nodemask+0x7e1/0x960 |
解决方案
调整内核参数
系统版本:CentOS 6.10 内核版本:Linux version 2.6.32-754.17.1.el6.x86_64
在sysctl.conf修改参数vm.zone_reclaim_mode和vm.min_free_kbytes。
1 | vim /etc/sysctl.conf |
1 | 备注:修改以上系统参数后,通过两天的观察,内核没有再抛“page allocation failure. order:0, mode:0x20”。 |
参考文章
https://access.redhat.com/solutions/90883
https://billtian.github.io/digoal.blog/2017/10/24/03.html
参数含义说明
min_free_kbytes
1 | This is used to force the Linux VM to keep a minimum number |
zone_reclaim_mode
1 | Zone_reclaim_mode allows someone to set more or less aggressive approaches to |
1 | 备注:zone_reclaim_mode默认为0即不启用zone_reclaim模式,1为打开zone_reclaim模式从本地节点回收内存;min_free_kbytesy允许内核使用的最小内存。 |
原理分析
在系统空闲内存低于 watermark[low]时,开始启动内核线程kswapd进行内存回收,直到该zone的空闲内存数量达到watermark[high]后停止回收。如果上层申请内存的速度太快,导致空闲内存降至watermark[min]后,内核就会进行direct reclaim(直接回收),即直接在应用程序的进程上下文中进行回收,再用回收上来的空闲页满足内存申请,因此实际会阻塞应用程序,带来一定的响应延迟,而且可能会触发系统OOM。这是因为watermark[min]以下的内存属于系统的自留内存,用以满足特殊使用,所以不会给用户态的普通申请来用。
min_free_kbytes大小的影响
1 | min_free_kbytes设的越大,watermark的线越高,同时三个线之间的buffer量也相应会增加。这意味着会较早的启动kswapd进行回收,且会回收上来较多的内存(直至watermark[high]才会停止),这会使得系统预留过多的空闲内存,从而在一定程度上降低了应用程序可使用的内存量。极端情况下设置min_free_kbytes接近内存大小时,留给应用程序的内存就会太少而可能会频繁地导致OOM的发生。 |
三个watermark的计算方法
1 | watermark[min] = min_free_kbytes换算为page单位即可,假设为min_free_pages。(因为是每个zone各有一套watermark参数,实际计算效果是根据各个zone大小所占内存总大小的比例,而算出来的per zone min_free_pages) watermark[low] = watermark[min] * 5 / 4 watermark[high] = watermark[min] * 3 / 2 |
1 | 备注:摘自“内存管理参数min_free_kbytes分析”,链接:https://www.dazhuanlan.com |