RocketMQ DefaultMQPushConsumer vs DefaultLitePullConsumer

1. 核心架构差异

DefaultMQPushConsumer (推送模式)

java 复制代码
// 服务端主动推送消息到消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group");
consumer.subscribe("TopicTest", "*");
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeConcurrentlyContext context) {
        // 服务端推送消息到这里
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

DefaultLitePullConsumer (拉取模式)

java 复制代码
// 客户端主动从服务端拉取消息
DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("group");
consumer.subscribe("TopicTest", "*");
consumer.start();

// 手动控制拉取
List<MessageExt> messages = consumer.poll();
// 业务处理
consumer.commitSync(); // 手动提交

2. 消费重试机制对比

PushConsumer 重试机制

特点:支持重试,且是自动重试,支持到消息级别

java 复制代码
// 自动重试 - 消息级别
public class DefaultMQPushConsumer {
    // 最大重试次数,默认16次
    private int maxReconsumeTimes = 16;
    
    // 重试消息进入 %RETRY% 队列
    // 重试间隔:1s, 5s, 10s, 30s, 1m, 2m, 3m, 4m, 5m, 6m, 7m, 8m, 9m, 10m, 20m, 30m, 1h, 2h
}

// 消费失败处理
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeConcurrentlyContext context) {
        try {
            // 业务处理
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        } catch (Exception e) {
            // 返回失败,自动进入重试队列
            return ConsumeConcurrentlyStatus.RECONSUME_LATER;
        }
    }
});

2.2 LitePullConsumer 重试机制

特点:没有内置的重试队列机制,不支持自动重试;要重试需要业务自己实现

java 复制代码
// 手动控制重试 - 需要业务代码实现
public class DefaultLitePullConsumer {
    // 没有内置的重试队列机制
    // 需要业务自己处理失败消息
}

// 手动重试示例
List<MessageExt> messages = consumer.poll(Duration.ofSeconds(10));
for (MessageExt message : messages) {
    try {
        processMessage(message);
        // 处理成功,记录偏移量
    } catch (Exception e) {
        // 处理失败,可以选择:
        // 1. 跳过此消息(可能丢失)
        // 2. 记录到死信队列手动处理
        // 3. 业务级重试逻辑
        log.error("Process message failed, msgId: {}", message.getMsgId(), e);
        
    }
}
// 批量提交,无法精确控制单条消息
consumer.commitSync();

3. 消费超时检查对比

PushConsumer 超时控制

特点:后台有消费超时检查,默认15min(从开始消费算起)。消费超时会将消息重发回broker(类似失败重试)。consumeTimeout可自行设置

java 复制代码
public class DefaultMQPushConsumer {
    // 消费超时时间,默认15分钟
    private long consumeTimeout = 15 * 60 * 1000;
    
    // 并发消费线程数控制
    private int consumeThreadMin = 20;
    private int consumeThreadMax = 64;
}

// 服务端会监控消费进度
// 如果消费线程卡住,Broker会重新投递消息

LitePullConsumer 超时控制

只有拉取超时,没有消费超时的检查

java 复制代码
public class DefaultLitePullConsumer {
    // 拉取超时控制
    private long pollTimeoutMillis = 10 * 1000;
    
    // 业务自己控制处理超时
    // 没有服务端超时检查
}

// 业务自己控制处理时间
List<MessageExt> messages = consumer.poll(Duration.ofSeconds(5));
long startTime = System.currentTimeMillis();
for (MessageExt message : messages) {
    // 业务需要自己控制单条消息处理超时
    if (System.currentTimeMillis() - startTime > 30000) {
        // 超时处理
        break;
    }
    processMessage(message);
}

4. 提交(Commit)机制对比

PushConsumer 提交机制

特点;仅可自动提交

java 复制代码
// 自动提交偏移量
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
        ConsumeConcurrentlyContext context) {
        // 返回 CONSUME_SUCCESS 后自动提交偏移量
        // 提交的是这批消息的最大偏移量
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

// 异步提交,默认5秒提交一次
// 提交到 Broker 的消费进度管理

4.2 LitePullConsumer 提交机制

特点:默认自动提交,可手动提交

java 复制代码
// 手动提交,更灵活的控制
public class DefaultLitePullConsumer {
    // 提交方式
    public void commitSync();                    // 同步提交
    public void commitSync(Map<MessageQueue, Long> offsetTable); // 指定偏移量提交
    public void commitAsync();                   // 异步提交
    
}

// 使用示例
List<MessageExt> messages = consumer.poll();
if (!messages.isEmpty()) {
    // 处理消息
    boolean allSuccess = true;
    for (MessageExt message : messages) {
        if (!processMessage(message)) {
            allSuccess = false;
            break;
        }
    }
    
    if (allSuccess) {
        // 全部成功才提交
        consumer.commitSync();
    }
}

5. 使用场景推荐

DefaultMQPushConsumer 使用场景

适合场景
  1. 常规业务消息处理
  2. 需要严格不丢消息的场景
  3. 希望服务端管理消费状态,减少客户端复杂度
  4. 消费逻辑相对固定,不需要精细控制
优势
  • 自动重试机制完善
  • 服务端管理消费进度
  • 开发简单,专注业务逻辑
  • 消息可靠性高

DefaultLitePullConsumer 使用场景

适合场景
  1. 批处理任务
  2. 需要精细控制消费逻辑
  3. 消息处理时间不确定,需要自定义超时
  4. 需要实现复杂的分支逻辑
具体用例
java 复制代码
// 用例1:批处理控制
List<MessageExt> batch = consumer.poll();
if (batch.size() >= BATCH_SIZE) {
    processBatch(batch);
    consumer.commitSync();
}

// 用例2:条件消费
List<MessageExt> messages = consumer.poll();
for (MessageExt msg : messages) {
    if (meetsCondition(msg)) {
        processMessage(msg);
    }
    // 不满足条件的消息跳过,但偏移量会提交
    // 需要更精细的偏移量管理
}

// 用例3:自定义重试
Map<String, Integer> retryCountMap = new HashMap<>();
List<MessageExt> messages = consumer.poll();
for (MessageExt msg : messages) {
    String msgId = msg.getMsgId();
    int retryCount = retryCountMap.getOrDefault(msgId, 0);
    if (retryCount < MAX_RETRY) {
        if (processWithRetry(msg)) {
            retryCountMap.remove(msgId);
        } else {
            retryCountMap.put(msgId, retryCount + 1);
            // 不提交此消息偏移量
        }
    } else {
        // 超过重试次数,进入死信队列
        sendToDLQ(msg);
    }
}

6. 总结对比

选择建议

  • 大部分业务场景推荐使用 DefaultMQPushConsumer
  • 只有在需要精细控制消费逻辑时才使用 DefaultLitePullConsumer
  • 从 Push 切换到 Pull 需要慎重,因为失去了很多内置的可靠性保障
相关推荐
KevinCyao几秒前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
迷藏4947 分钟前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
wuxinyan1231 小时前
Java面试题47:一文深入了解Nginx
java·nginx·面试题
新知图书1 小时前
搭建Spring Boot开发环境
java·spring boot·后端
冰河团队1 小时前
一个拉胯的分库分表方案有多绝望?整个部门都在救火!
java·高并发·分布式数据库·分库分表·高性能
洛_尘1 小时前
Java EE进阶:Linux的基本使用
java·java-ee
宸津-代码粉碎机1 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
MaCa .BaKa1 小时前
47-心里健康咨询平台/心理咨询系统
java·spring boot·mysql·tomcat·maven·intellij-idea·个人开发
木子欢儿2 小时前
Docker Hub 镜像发布指南
java·spring cloud·docker·容器·eureka
Devin~Y2 小时前
高并发电商与AI智能客服场景下的Java面试实战:从Spring Boot到RAG与向量数据库落地
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag