mq生产环境正常生产和消费都挺稳定的,99.999%应该都没问题的,比较稳定。今天刚好碰到过一例因为写超时导致异常问题。
2023-02-23 21:19:58.449 TID:8b8a430ff3d34213a374de3550822503.789.16771583982424385 [ERROR] [NettyClientPublicExecutor_2] [c.g.m.m.p.m.UserTaskOraProducer:90] --- UserTaskOraProducer发送失败,key:task_post_be_highlightU910943377267384320,typeCode:task_post_be_highlight +1 21:19:59.018 2023-02-23 21:19:58.449 TID:8b8a430ff3d34213a374de3550822503.727.16771583977572409 [WARN ] [XNIO-1 task-43] [RocketmqClient:130] --- sendKernelImpl exception, resend at once, InvokeID: 4921002808992973274, RT: 204ms, Broker: MessageQueue [topic=marketing-badge-task-gray, brokerName=RaftNode00, queueId=1] +2 21:19:59.018 org.apache.rocketmq.client.exception.MQBrokerException: CODE: 2 DESC: [TIMEOUT_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: 203ms, size of queue: 1 +3 21:19:59.018 For more information, please visit the url, http://rocketmq.apache.org/docs/faq/ +4 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl.processSendResponse(MQClientAPIImpl.java:665) +5 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessageSync(MQClientAPIImpl.java:505) +6 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage$original$gcDrtLSO(MQClientAPIImpl.java:487) +7 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage$original$gcDrtLSO$accessor$n9m8eZyq(MQClientAPIImpl.java) +8 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl$auxiliary$uyI9DykF.call(Unknown Source) +9 21:19:59.018 at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:86) +10 21:19:59.018 at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java)
我们用rocketMQ发消息的流程,大致就是首先producer向broker发送消息写入请求,broker接收到请求之后会放进队列中(这个队列大小默认10000),然后有一个线程数为1的线程来从队列取消息去执行消息写入。
正常这个流程没啥,但是一旦broker端挤压了大量的请求而得不到及时的处理。消息发送端默认的超时时间是3s,这样数据量大的时候就大概率会出现不少超时的情况,这些就会造成大量的无效处理。
所以rocketMQ就引入了快速失败机制,简单来说就是开了个定时任务,默认是将队列中超过200ms的请求直接取消,直接向客户端返回失败。
很多人认为都去github上去提了issue,认为SYSTEM_ERROR类型的错误,broker端都做了重试,为啥 SYSTEM_BUSY遗漏了,觉得这是一个bug。
但是作者的回复是,当broker繁忙的时候,自动重试无疑只会增加mq的压力,起不到关键的帮助。
解决方案:
将 waitTimeMillsInSendQueue 调大,默认是200ms
开启 transientStorePoolEnable
扩容
简单讲一下第二种,开启 transientStorePoolEnable 的方式
transientStorePoolEnable置为true之后,相当于消息直接写入到堆外内存,然后消息一批批写入到pageCache,以此来降低对pageCache的压力
————————————————
版权声明:本文为CSDN博主「白衣神棍」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29914229/article/details/126831516