RocketMQ消息生产

本文详细介绍了如何在RocketMQ中使用SpringBootstarter实现消息的顺序、事务和延时/定时发送,包括生产者和消费者的示例代码以及不同类型的消费模式。
摘要由CSDN通过智能技术生成

本文只提供生产者和消费者部分的示例代码,其它配置部分见RocketMQ消息客户端生产与消费的基本实现
#依赖框架
JDK: java version “1.8.0_391”
RocketMQ SDK: rocketmq-spring-boot-starter:2.2.3

消息分类

按消息类型

按照消息自身特性可分为:普通消息、顺序消息、事务消息、延时\定时消息。

普通消息

利用事件驱动的特性,为应用服务之间解耦,消息提供基本的数据传递。
使用示例见:RocketMQ消息客户端生产与消费的基本实现

顺序消息

消费者消费消息的顺序与生产者发送消息的顺序一致;使用这类消息需要遵循如下约束:

  1. 生产者发送所有顺序消息时提供唯一的hashKey,RocketMQ服务端根据hashKey散列匹配到一个固定的消息队列,保证所有顺序消息存储在同一个消费队列中;
  2. 生产者发送消息必须是单一生产者串行发送消,保证消息是顺序发送;
  3. 生产和消费消息时要有限重试,重试会阻碍后续消息的生产或消费;
  4. 消费者接收消息时需要指定消费模式为"ConsumeMode.ORDERLY",此模式为“顺序消费”,保证消费者用单一线程依次消费同一个队列的消息。
  5. 不同的消息组尽量分散在不同的队列中,保证消费负载均衡

生产者示例代码

// 创建 RocketMQ 的 短信Message 实例
        List<Message<String>> messageList = new ArrayList<>(1000);
        for (int i = 0; i < 1000; i++) {
            messageList.add(MessageBuilder
                    .withPayload("顺序消息" + i)
                    .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo + i)
                    .build());
        }
        // mq根据hashKey匹配固定的队列
        String hashKey = "CZ001";
        //发送短信通知消息
        SendResult smsSendResult = rocketMQTemplate.syncSendOrderly("smsOrderlyTopic:orderlyTag", messageList, hashKey);
        if (smsSendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
            logger.info("顺序消息已经发送");
            return r;
        }

消费者示例代码

@Component
@RocketMQMessageListener(
        topic = "smsOrderlyTopic",
        consumerGroup = "smsOrderlyConsumerGroup",
        consumeMode = ConsumeMode.ORDERLY
)
public class SMSOrderlyTopicListener implements RocketMQListener<MessageExt> {

    private static final Logger logger = LoggerFactory.getLogger(SMSTopicListener.class);

    @Override
    public void onMessage(MessageExt msgExt) {
        // 执行本地事务逻辑,返回事务状态
        try {
            String bodyStr = new String(msgExt.getBody());
            logger.info("消息消费开始:{}", bodyStr);
        } catch (Exception e) {
            logger.error("交易消息消费失败!", e);
            throw e;
        }
    }
}

事务消息

提供了分布式事务解决方案,见<<可靠消息服务事务>>

延时\定时消息

定时消息为RocketMQ 5.X版本新特性,最终展现效果与延时消息类似;延时消息指定了消息的发送时间与消费时间的时间差,定时消息指定了消息被消费的具体时间。
在RocketMQ 4.X版本中,将时间分为了18个等级,生产者通过指定时间等级来控制延时发送的时间,时间等级如图:
在RocketMQ 5.X版本中,可自定义延时时间和定时时间,不同版本时间范围不一致,文章编写当前的最新版本时间范围是:0-40天。
生产者代码示例:

//延时发送代码
String reqNo = TransactionIdGenerator.generateReqTransactionId();

        // 创建 RocketMQ 的 短信Message 实例
        Message<String> smsMessage = MessageBuilder
                .withPayload("发送延时消息")
                .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo)
                .build();

        //发送短信通知消息
        SendResult smsSendResult = rocketMQTemplate.syncSendDelayTimeMills("smsTopic:delayTag", smsMessage, 20000L);
        if (smsSendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
            logger.info("发送延时消息已经发送");
            return r;
        }
//定时发送代码
String reqNo = TransactionIdGenerator.generateReqTransactionId();

        // 创建 RocketMQ 的 短信Message 实例
        Message<String> smsMessage = MessageBuilder
                .withPayload("发送定时消息")
                .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo)
                .build();

        Date date = new Date();
        //发送短信通知消息
        SendResult smsSendResult = rocketMQTemplate.syncSendDeliverTimeMills("smsTopic:deliverTag", smsMessage, date.getTime() + 30000L);
        if (smsSendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
            logger.info("定时消息已经发送");
            return r;
        }

消费者示例代码与普通消费者一致。

按生产者发送类型

同步发送

生产者发送消息后同步等待消息发送的结果;示例代码见本文【消息分类】章节代码。

异步发送

生产者发送消息后,不阻塞线程,异步等待消息发送结果。
示例代码:

String reqNo = TransactionIdGenerator.generateReqTransactionId();

        // 创建 RocketMQ 的 短信Message 实例
        Message<String> smsMessage = MessageBuilder
                .withPayload("发送普通消息。")
                .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo)
                .build();

        //发送短信通知消息
        rocketMQTemplate.asyncSend("smsTopic:asyncTag", smsMessage, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                logger.info("异步消息已经发送");
            }

            @Override
            public void onException(Throwable e) {
                logger.error("异步消息发送失败");
            }
        });

异步发送方式不支持发送延时、定时消息;在发送顺序消息时需要控制消息的发送顺序。

单边发送

生产者发送消息后不需要接收消息的发送状态,示例代码:

String reqNo = TransactionIdGenerator.generateReqTransactionId();

        // 创建 RocketMQ 的 短信Message 实例
        Message<String> smsMessage = MessageBuilder
                .withPayload("单边消息")
                .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo)
                .build();

        //发送短信通知消息
        //单边消息支持顺序发送
        rocketMQTemplate.sendOneWay("smsTopic:oneWayTag", smsMessage);

同步等待消息消费结果

生产者发送消息后阻塞线程,同步等待消费者完成消息消费,接收消费者消费完成后返回的结果。
生产者示例代码:

String reqNo = TransactionIdGenerator.generateReqTransactionId();
//同步等待
// 创建 RocketMQ 的 短信Message 实例
Message<String> smsMessage = MessageBuilder
        .withPayload("等待响应消息")
        .setHeader(RocketMQHeaders.KEYS, "SMS_" + reqNo)
        .build();
//返回值为MessageExt会返回所有消息内容,其它类型只会返回body
//sendAndReceive支持发送顺序消息,消费者需要制定顺序接收
MessageExt messageExt = rocketMQTemplate.sendAndReceive("smsReplyTopic:replyTag", smsMessage, MessageExt.class, 5*1000L);
R<String> result = JSON.parseObject(new String(messageExt.getBody()), new TypeReference<R<String>>(){});
if (result.getCode().equals(R.SUCCESS)) {
    logger.info("成功接收到消费结果");
    return r;
}

这种发送方式下,消费者消费消息时必须返回消费结果,否者生产的线程会一直阻塞到等待超时时间。消费者示例代码:

@Component
@RocketMQMessageListener(
        topic = "smsReplyTopic",
        consumerGroup = "smsReplyConsumerGroup"
//        consumeMode = ConsumeMode.ORDERLY
)
public class SMSRocketMQReplyListener implements RocketMQReplyListener<MessageExt, R<String>> {

    private static final Logger logger = LoggerFactory.getLogger(SMSRocketMQReplyListener.class);

    @Override
    public R<String> onMessage(MessageExt message) {
        // 执行本地事务逻辑,返回事务状态
        try {
            String bodyStr = new String(message.getBody());
            logger.info("消息消费开始:{}", bodyStr);
            return R.ok("消息消费成功");
        } catch (Exception e) {
            logger.error("交易消息消费失败!", e);
            throw e;
        }
    }
}

异步等待消息消费结果

生产者发送消息后不阻塞线程,异步等待消费者完成消息消费,接收消费者消费完成后返回的结果。
生产者示例代码:

String reqNo = TransactionIdGenerator.generateReqTransactionId();

        //发送短信通知消息

        // 创建 RocketMQ 的 短信Message 实例
        Message<String> smsSyMessage = MessageBuilder
                .withPayload("异步等待响应消息")
                .setHeader(RocketMQHeaders.KEYS, "sy_SMS_" + reqNo)
                .build();
        rocketMQTemplate.sendAndReceive("smsReplyTopic:replyTag", smsSyMessage, new RocketMQLocalRequestCallback<MessageExt>() {
            @Override
            public void onSuccess(MessageExt message) {
                try {
                    Thread.sleep(1000L*10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                logger.info("【异步等待响应消息】异步接收成功");
                logger.info("【异步等待响应消息】返回内容:{}", new String(message.getBody()));
            }

            @Override
            public void onException(Throwable e) {
                logger.info("【异步等待响应消息】异步接收失败");
            }
        }, 5*1000L);

消费者消费完成后需要返回消费结果,否则生产者接收失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值