RocketMQ进阶(一)

本文介绍了如何在SpringBoot中集成RocketMQ生产者,包括pom.xml配置、application.yml设置以及具体代码实现,展示了消息发送的过程。接着,文章深入解析了RocketMQ生产者的发送消息实现,从DefaultMQProducer到内部的DefaultMQProducerImpl,逐步剖析消息发送的各个步骤,包括同步和异步发送。最后探讨了RocketMQ生产者启动时的逻辑,为理解RocketMQ工作原理打下基础。
摘要由CSDN通过智能技术生成

今天的博客主题

      MQ消息中间件 --》RocketMQ --》RocketMQ进阶(一)


本文主要讲解RocketMQ生产者实现及底层实现原理刨根问底

对于使用原生Java项目来实现的例子就不多说了,官方文档都有

样例地址:https://github.com/apache/rocketmq/blob/master/docs/cn/RocketMQ_Example.md

主要看下springboot是怎么集成RocketMQ,并实现生产者发送消息。

springboot集成rocketmq生产者实现

pom.xml文件引入MQ依赖jar包

<!-- rocketmq依赖 -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.0.3</version>
</dependency>

application.yml配置文件添加配置

rocketmq: 
    #服务地址
    name-server: 10.10.16.20:9876
      #生产者配置
      producer:
         #生产组名
         group: PG_DEMO
         #主题
         topic: TOPIC_DEMO_ONE
        #标签
        tag: TAG_ONE

具体代码实现

@RestController
@RequestMapping("/producerDemo")
public class ProducerDemo {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Value(value = "${rocketmq.producer.topic}")
    private String topic;
    @Value(value = "${rocketmq.producer.tag}")
    private String tag;

    /**
     * 同步发送消息到MQ
     */
    @RequestMapping("/syncSendMsg2MQ")
    public String syncSendMsg2MQ(){
        // 发送的消息体,消息体必须存在
        String msg = "Hello World " + LocalDateTime.now();
        // 业务主键作为消息key
        String key = "123456";
        // 发送目的地  TOPIC:TAG
        String destination = topic + ":" + tag;
        // 构建消息
        Message message = MessageBuilder.withPayload(msg)
                .setHeader(RocketMQHeaders.KEYS, key)
                .build();
        SendResult sendResult = rocketMQTemplate.syncSend(destination, message);
        if(sendResult.getSendStatus() == SendStatus.SEND_OK){
            System.out.println(sendResult.getMsgId() + " : " + sendResult.getSendStatus());
            return LocalDateTime.now() +" 》》SUCCESS 》》 "  + sendResult.getMsgId() + " : " + sendResult.getSendStatus();
        }else{
            return LocalDateTime.now() +" 》》 FAIL 》》 "  + sendResult.getMsgId() + " : " + sendResult.getSendStatus();
        }
    }
}

测试

本来是想放在启动类下,但是在实际中不会这么做。就创建个controller,启动项目来真正模拟环境测试下

访问,浏览器返回:2019-07-08T17:12:52.363 》》SUCCESS 》》 0A0A33DB31DC18B4AAC227BE22DD0000 : SEND_OK

编辑器控制台输出:0A0A33DB31DC18B4AAC227BE22DD0000 : SEND_OK

打开rocketmq控制台确定消息是否发送到了服务端。

没问题,可以查到那条消息,而且发送时间一致。

到这里发送者已经集成到springboot里了,并成功发送了消息到服务端。

这也太简单了,5分钟学会应用rocketmq。能应用...当然这些不行的。知己知彼方能百战不殆

下面开始对生产者发送消息进行刨根问底。

 

rocketmq-spring-boot-starter是对rocketmq的一个封装,不用在像原生java项目那些去写控制生产者消费者的启动销毁。

只需要关注消息体的组成即可,其余的都交给spring来管理了。

看下rocketmq-spring-boot-starter的包结构

这里面做的很简单就是将比较频繁使用到的给封装成Bean,统一由spring管理,当你用的时候直接通过bean方式注入即可。

具体的实现也比较简单,自己也可以实现一个starter的。就不浪费时间细说了,自己找到源码看下。

通过上面的代码块看到了,在发送消息的时候需要将 RocketMQTemplate 通过bean注入的方式给注入进来,就能用了。

RocketMQTemplate的内部结构:

可以看到提供了许多方法,支持不同的消息发送姿势。比如同步发送,异步发送,单向发送,消息延迟发送等等...

值得注意的是在这些方法的参数类型,Message使用的都是Spring的Message,可以说是对spring Message的一个支持,为了是方便从其他MQ能快速切换到RocketMQ。

这个是rocketmq在做starter的时候对消息发送的一个封装。但具体实现发送还需要看底层实现

/**
 * Same to {@link #syncSend(String, Message)} with send timeout specified in addition.
 * @param destination formats: `topicName:tags`
 * @param message     {@link org.springframework.messaging.Message}
 * @param timeout     send timeout with millis
 * @param delayLevel  level for the delay message
 * @return {@link SendResult}
 */
public SendResult syncSend(String destination, Message<?> message, long timeout, int delayLevel) {
    // 验证消息是否为空,为空则抛出异常
    if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
        log.error("syncSend failed. destination:{}, message is null ", destination);
        throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
    }
    // 消息不为空,发送消息
    try {
        long now = System.currentTimeMillis();
        // message之间的一个转换。SpringMessage To RocketMQMessage
        org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
            charset, destination, message);
        // 设置消息的延迟发送级别
        if (delayLevel > 0) {
            rocketMsg.setDelayTimeLevel(delayLevel);
        }
        // 调用rocketmq-client提供的方法,发送消息
        SendResult sendResult = producer.send(rocketMsg, timeout);
        // 计算发送时间
        long costTime = System.currentTimeMillis() - now;
        log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId());
        return sendResult;
    } catch (Exception e) {
        log.error("syncSend failed. destination:{}, message:{} ", destination, message);
        throw new MessagingException(e.getMessage(), e);
    }
}

继续深入 producer.send()

在深入前先看下这个producer的来头:DefaultMQProducer  producer

1. 这个类是发送消息的应用程序入口
2. 对于暴露出去的getter/setter方法都可以调优,默认的配置已适应于大多场景。
3. 这个类里聚合了各种send方法来将消息发送到服务端。每个方法都有利有弊。在编写之前最好先了解它们的优缺点,来自RocketMQ官方的忠告!!!
4. 它是线程安全的。
5. 是MQProducer接口实现类。
public class DefaultMQProducer extends ClientConfig implements MQProducer {
    ....省略实现代码
}

DefaultMQProducer 所实现的就是MQProducer里的这些。

DefaultMQProducer 里提供了不同的构造函数,来方便实例化它

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值