RocketMQ消息发送模式:同步与异步实现详解

RocketMQ提供了灵活的发送模式以适应不同业务场景的需求,主要包括同步发送、异步发送和单向发送三种方式。下面我将详细介绍各种模式的实现方法、适用场景及最佳实践。

一、同步发送模式

1.1 核心特点

  • 阻塞等待:发送线程会阻塞直到收到Broker响应
  • 强一致性:明确知道消息是否发送成功
  • 可靠性高:自动重试机制(默认重试2次)
  • 性能中等:TPS约5000-10000(取决于网络和配置)

1.2 代码实现

// 创建生产者实例
DefaultMQProducer producer = new DefaultMQProducer("sync_producer_group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();

try {
    // 构建消息
    Message msg = new Message("OrderTopic", 
                            "PaySuccess", 
                            "order_12345".getBytes());
    
    // 同步发送(关键方法)
    SendResult sendResult = producer.send(msg);
    
    System.out.printf("同步发送成功! MsgId:%s, Queue:%s%n",
                     sendResult.getMsgId(),
                     sendResult.getMessageQueue().getQueueId());
} catch (Exception e) {
    // 处理发送失败(自动重试后仍失败)
    System.err.println("消息发送失败: " + e.getMessage());
    // 业务补偿逻辑
    compensateSendFailure(msg);
} finally {
    producer.shutdown();
}

1.3 关键配置参数

// 设置发送超时时间(默认3000ms)
producer.setSendMsgTimeout(5000);

// 设置同步发送失败重试次数(默认2次)
producer.setRetryTimesWhenSendFailed(3);

// 设置Broker不可用时的规避时间(默认1000*10ms)
producer.setSendLatencyFaultEnable(true);

1.4 适用场景

  • 金融交易:支付结果通知
  • 订单创建:需要确保消息必达
  • 重要状态变更:如库存扣减

二、异步发送模式

2.1 核心特点

  • 非阻塞:发送后立即返回,通过回调处理结果
  • 高性能:TPS可达20000+
  • 可靠性保障:失败时有回调通知
  • 资源占用:需要维护回调线程池

2.2 代码实现

DefaultMQProducer producer = new DefaultMQProducer("async_producer_group");
producer.setNamesrvAddr("127.0.0.1:9876");

// 设置异步发送失败重试次数(默认2次)
producer.setRetryTimesWhenSendAsyncFailed(2);

producer.start();

// 构建消息
Message msg = new Message("LogTopic", 
                        "UserLogin", 
                        getUserLoginJson().getBytes());

// 异步发送(关键方法)
producer.send(msg, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
        // 成功处理逻辑
        System.out.printf("异步发送成功! MsgId:%s%n", sendResult.getMsgId());
        updateSendSuccessMetric();
    }
    
    @Override
    public void onException(Throwable e) {
        // 失败处理逻辑(已自动重试过)
        System.err.println("异步发送失败: " + e.getMessage());
        recordSendFailure(msg, e);
        
        // 可选择人工介入或持久化后定时重试
        asyncRetryQueue.add(msg);
    }
});

// 注意:此处立即返回,不要在此后立即shutdown

2.3 回调线程池配置

// 自定义回调线程池(默认使用Netty的EventLoopGroup)
producer.setCallbackExecutor(Executors.newFixedThreadPool(
    16, 
    new ThreadFactory() {
        private AtomicInteger count = new AtomicInteger(0);
        
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("AsyncSendCallback-" + count.incrementAndGet());
            return thread;
        }
    }
));

2.4 适用场景

  • 日志收集:允许短暂延迟
  • 通知类消息:如站内信
  • 高吞吐场景:秒杀抢购记录

三、单向发送模式(Oneway)

3.1 核心特点

  • 只管发送:不等待响应也不回调
  • 最高性能:TPS可达50000+
  • 可靠性最低:可能丢失消息
  • 资源消耗最小:无响应处理开销

3.2 代码实现

DefaultMQProducer producer = new DefaultMQProducer("oneway_producer_group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();

try {
    Message msg = new Message("MonitorTopic",
                            "CPU_ALERT",
                            getHostStats().getBytes());
    
    // 单向发送(关键方法)
    producer.sendOneway(msg);
    
    System.out.println("单向发送完成(无结果确认)");
} finally {
    producer.shutdown();
}

3.3 适用场景

  • 心跳检测:允许丢失部分数据
  • 实时性要求低:如用户行为埋点
  • 内部监控:集群节点状态上报

四、三种模式对比

特性同步发送异步发送单向发送
响应方式阻塞等待响应回调通知结果无响应
吞吐量中等(5k-10k TPS)高(20k+ TPS)极高(50k+ TPS)
可靠性最高
实现复杂度简单中等简单
资源消耗中等较高(回调线程)最低
典型场景支付交易日志收集心跳检测

五、高级特性与最佳实践

5.1 批量发送优化

// 同步批量发送
List<Message> messages = new ArrayList<>(100);
for(int i=0; i<100; i++) {
    messages.add(new Message("BatchTopic", 
                          "TagA", 
                          ("Msg"+i).getBytes()));
}

SendResult result = producer.send(messages);

// 异步批量发送
producer.send(messages, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
        // 整批成功
    }
    
    @Override
    public void onException(Throwable e) {
        // 整批失败
    }
});

注意事项

  • 单批次建议不超过1MB
  • 同一批次消息应有相同Topic
  • 不支持延迟消息/事务消息的批量发送

5.2 发送超时管理

// 全局超时设置(作用于所有发送类型)
producer.setSendMsgTimeout(5000);

// 单次发送特殊超时(仅同步发送有效)
long begin = System.currentTimeMillis();
try {
    SendResult result = producer.send(msg, 10000); // 单独设置10秒超时
} catch (RemotingTooMuchRequestException e) {
    long cost = System.currentTimeMillis() - begin;
    System.out.println("实际等待时间: " + cost + "ms");
}

5.3 故障规避机制

// 开启Broker故障延迟规避(默认false)
producer.setSendLatencyFaultEnable(true);

// 自定义规避策略(高级用法)
producer.setLatencyFaultTolerance(new LatencyFaultTolerance() {
    @Override
    public void updateFaultItem(String brokerName, long currentLatency) {
        // 根据延迟动态调整规避时间
    }
});

六、生产环境建议

6.1 性能调优参数

# 发送线程池数量(默认CPU核数)
rocketmq.producer.sendMessageThreadPoolNums=16

# 异步发送队列深度(默认5000)
rocketmq.producer.asyncSendThreadPoolQueueCapacity=10000

# 压缩消息阈值(默认4KB)
rocketmq.producer.compressMsgBodyOverHowmuch=4096

6.2 错误处理策略

同步发送失败处理

try {
    sendResult = producer.send(msg);
} catch (MQClientException e) {
    // 客户端异常(参数错误等)
    log.error("客户端错误:", e);
} catch (RemotingException e) {
    // 网络异常
    if(retryCount.getAndIncrement() < MAX_RETRY) {
        // 自定义重试
        return doSendWithRetry(msg);
    }
} catch (MQBrokerException e) {
    // Broker异常(根据响应码处理)
    switch(e.getResponseCode()) {
        case ResponseCode.TOPIC_NOT_EXIST:
            createTopic(msg.getTopic());
            break;
        case ResponseCode.SERVICE_NOT_AVAILABLE:
            Thread.sleep(1000);
            break;
    }
}

异步发送失败处理

// 在SendCallback.onException中实现
public void onException(Throwable e) {
    if(e instanceof MQBrokerException) {
        // Broker返回的错误
    } else if(e instanceof RemotingException) {
        // 网络问题
    }
    
    // 持久化到本地磁盘
    persistToDisk(msg);
    
    // 启动定时任务重试
    retryScheduler.schedule(() -> {
        producer.send(msg, this); // 使用相同的callback
    }, 1, TimeUnit.MINUTES);
}

七、监控与运维

7.1 关键监控指标

指标名称预警阈值监控方式
发送平均耗时>500msPrometheus+Grafana
异步发送积压量>5000RocketMQ控制台
发送失败率>1%日志分析
Broker响应时间>300ms分布式追踪系统

7.2 运维命令

# 查看生产者状态
mqadmin producerConnection -n 127.0.0.1:9876 -g producer_group

# 查看发送TPS
mqadmin producerStatus -n 127.0.0.1:9876 -g producer_group

# 重置生产者客户端(强制清理)
mqadmin cleanExpiredProducer -n 127.0.0.1:9876

八、版本兼容性

RocketMQ版本同步发送变化异步发送增强
4.0.x基础支持基础回调支持
4.3.x增加超时精确控制支持批量异步发送
4.6.x优化重试机制回调线程池可配置化
4.9.x增强Broker故障检测支持回调结果上下文传递

通过合理选择发送模式并配合适当的错误处理和性能调优,可以充分发挥RocketMQ在高并发分布式场景下的优势。建议根据业务场景的可靠性要求、实时性需求和系统资源情况综合评估后选择最合适的发送方式。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰alk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值