线上Rocketmq消息堆积了,快来试试解决

236 阅读2分钟

轻量级改动

1. 增加消费者线程数

  • 难度:低
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("OrderTopic", "*");

// 增加消费者线程数
consumer.setConsumeThreadMin(20);
consumer.setConsumeThreadMax(64);

consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            processMessage(msg);
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    private void processMessage(MessageExt msg) {
        System.out.printf("Receive message: %s%n", new String(msg.getBody()));
    }
});

consumer.start();

2. 减少每次拉取的消息数量

  • 难度:低
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤

consumer.setConsumeMessageBatchMaxSize(10); // 设置每次拉取消息的数量

3. 使用Tag过滤

  • 难度:低
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤

consumer.subscribe("OrderTopic", "TagA || TagB"); // 只订阅TagA和TagB的消息

中等改动

4. 使用异步处理

  • 难度:中
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤

import java.util.concurrent.CompletableFuture;

consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            CompletableFuture.runAsync(() -> {
                processMessage(msg);
            });
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    private void processMessage(MessageExt msg) {
        System.out.printf("Receive message: %s%n", new String(msg.getBody()));
    }
});

5. 增加JVM堆内存

  • 难度:中
  • 是否需要修改应用代码:否
  • 是否需要修改RocketMQ配置:否

操作步骤: 调整消费者应用的JVM启动参数,增加堆内存,并重启消费者应用。

java -Xms4g -Xmx8g -jar consumer-application.jar

重量级改动

6. 增加消费者实例

  • 难度:中到高
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤: 启动多个消费者实例,加入相同的消费者组。

// 启动多个消费者实例
DefaultMQPushConsumer consumer1 = new DefaultMQPushConsumer("ConsumerGroup");
consumer1.setNamesrvAddr("127.0.0.1:9876");
consumer1.subscribe("OrderTopic", "*");

DefaultMQPushConsumer consumer2 = new DefaultMQPushConsumer("ConsumerGroup");
consumer2.setNamesrvAddr("127.0.0.1:9876");
consumer2.subscribe("OrderTopic", "*");

// 配置和启动消费者

7. 增加Broker实例

  • 难度:高
  • 是否需要修改应用代码:否
  • 是否需要修改RocketMQ配置:是

操作步骤

  1. 配置并部署新的Broker实例。
  2. 将新的Broker实例添加到RocketMQ集群中。
  3. 重新分配主题到新的Broker实例,确保负载均衡。

示例步骤

  • 修改Broker配置文件(broker.conf)。
  • 在RocketMQ集群中注册新的Broker实例。
  • 使用RocketMQ控制台或命令行工具重新分配主题。

8. 优化消息处理逻辑

  • 难度:高
  • 是否需要修改应用代码:是
  • 是否需要修改RocketMQ配置:否

操作步骤: 分析和优化消费者的业务逻辑,减少耗时操作和不必要的计算。

public class OptimizedMessageListener implements MessageListenerConcurrently {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            processMessage(msg);
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    private void processMessage(MessageExt msg) {
        // 优化的消息处理逻辑
        System.out.printf("Receive message: %s%n", new String(msg.getBody()));
    }
}