测试过程:
在对rocketmq做非功能测试时出现将master kill之后slave CPU高的问题
问题分析:
有可能出现问题的地方有下面几个:
1、mq slave自身机制问题
2、producer发送消息频率太高
3、consmer拉取消息频率高
一开始怀疑是mq slave自身机制问题,怀疑安装的时候参数配置不对,搜索了很多资料,问了阿里rocketmq的开发人员,根据他们提供的方法配置了mq系统参数还是没有解决,后面查看consumer进程的cpu时,发现consumer的cpu也很高,因此怀疑是不是mq客户端出现了问题。
使用tcpdump -i eth1 host xxxx.xxx.xx.xx -vvv 发现consumer和slave之间的通信次数非常之多,大概找到了原因,在master被kill之后,consumer和slave之间的通信频率太过于高导致的slave cpu高。问题定位出来了,但是原因还没有找到,为此需要研究mq consumer客户端的代码。
客户端代码分析:
首先是DefaultMQPushConsumerImpl的start方法,跟踪代码发现pullMessageService start方法启动了一个线程,如下面图片所示
进入到PullMessageService run方法查看
发现这个线程干的事情就是不断从pullRequestQueue队列里拿PullRequest拉取任务去执行,那么PullRequest是什么时候被放到这个pullRequestQueue里的呢?
查看代码有调用pullRequestQueue put方法的有下面这个方法
发现是在PullCallBack方法的onSuccess方法里会调用,这个PullCallBack onSuccess是在消息拉取成功之后的回调方法,也就是成功之后继续拉取。
进入调用到pullCallBack的方法里,不断往下找
找到这个方法,可以看到这个方法里将根据拉取结果的reponse code做不同操作
为了看consumer和slave broker之间是怎么通信的,使用tcpdump -i eth1 host xxxx.xxx.xx.xx -w tcp.cap将consumer和slave broker之间的通信信息记录下来,然后使用wireshark分析,发现consumer向consumer发送code为11的请求,slave broker向consumer返回code为20
发现20是立马重新拉取消息
至此问题差不多明确,查找相关资料,最终原因是,mq配置成asyn master,同步刷盘,有些消息来不及同步到slave时,master就被kill掉,导致consumer去拉取slave的消息时,消息的offset超前,找不到对应的commit log,slave broker就返回立马再次拉取,这就使得consumer和slave之间通信频率很高从而导致consumer和slave CPU都很高。
找到原因问题就比较好解决,有两个解决方法:
1、将broker配置成sync broker,这样子消息只有落磁盘和同步到slave才会返回,不过之前试验过,broker性能下降很多;
2、在processPullResponse方法里加上sleep 1000,让consumer和slave之间通信不要这么频繁
使用第二个方法重新实验没有再出现CPU高的情况