使用阿里的rocketmq作为消息中间件也有两年多了,还算稳定。期间从4.6版本升到了4.8.升级后,莫名其妙的错少了不少。不过最近比较郁闷,有个主体的消费,总是把内存搞崩了。
这个主题是监控主库表的变化,会发mq,做相应的变更检查,而后触发业务。所以存在很高的并发,发送消息时也启动了多线程去发。本来用了很久,也相安无事,看着mq也扛得住,不过最近消费端崩了几次,都是内存很快吃到极限,然后他就躺平了。
当然是百思不得其解。
最近的消息量确实是增加了不少,有时候一天的量也快过亿了。不过消费端跟不上。后来分析了下,由消费端设计的问题在里面,当时没有考虑对接收到的消息做一层换层,批处理,所以一条消息的处理速度要1s左右。按照1s处理一条计算,一天能够一个消费者能处理的也就8万多。这块业务已经成长的太复杂了,优化是来不及了,不拿出点勇气来,还真不敢动,所以开了100多个消费者。
1.PullMessageServiceScheduledThread,一个消费者对应1个
2.PullMessageService,一个消费者对应4个
3.NettyClientPublicExecutor 一个消费者对应 cpu核数(n)个
4.ConsumeMessageThread 一个消费者对应同消费者m个数个(m)
5.MQClientFactoryScheduledThread 一个消费者1个
6.CleanExpireMsgScheduledThread一个消费者1个
7.MQClientFactoryScheduledThread一个消费者1个
8.RequestHouseKeepingService一个消费者1个
9.ClientHouseKeepingService一个消费者1个
10.NettyClientWorkerThread一个消费者对应4个
11.NettyClientSelector一个消费者1个
12.RebalanceService一个消费者3个
比较过分的就是ConsumerMessageThread,消费者线程会跟消费者设定数笛卡尔积。这也就意味着一个容器下面不能无限开消费者,这样会死的太快。也就是说,如果没有从代码上做批处理的话,单纯相靠人多力量大的方法去消费的话,是行不通的,这就有些令人沮丧了。
不过也不是毫无办法,后来在官网售卖的rocketmq云产品上发现点解决方案,他给了一个计算公式如下:
而我在本地的部署恰好是两主两从配置,当时为了加快消费速度,在客户端配置每个broker队列数512个,当时给mq机器的性能很好,以为加大broker线程数,能加大吞吐量,现在通过这个公式明白了,完全理解错了,broker开几个队列,相应的消费端也会对应打开端口去扫描队列,无形中加载了消费端的负担。
所以后来,我将broker的队列改成了60,mq导致内存爆炸的问题得以解决。