在上篇中,了解RocketMQ的基本概念,以及安装好RocketMQ,启动后。进行代码实际操作练习

本篇主要练习三种发送方式

一、基础项目创建

需要创建两个项目,来表示消费者和生产者

创建两个SpringBoot项目,并导入maven和配置好application.yaml

maven需要导入rocketmq-common、rocketmq-client、fastjson

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-common</artifactId>
            <version>4.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.49</version>
        </dependency>
    </dependencies>

application.yaml

rocketmq:
  consumer:
    # RocketMQ
    namesrvAddr: your`s ip:9876
   
    groupName: test-demo
    
    instanceName: consumer.demo
  producer:
    
    sendMsgTimeout: 10000
    
    maxMessageSize: 999999999
    
    compressOver: 40000
  topic: test-demo
  # tag , "0||1||2"
  tag: "111"

RocektMQConsumer项目中,添加配置类,用于创建Consumer,并启动该项目

@Configuration
public class RocketMQConfig {
    @Value("${rocketmq.consumer.groupName}")
    private String groupName;
    @Value("${rocketmq.consumer.namesrvAddr}")
    private String namesrvAddr;
    @Value("${rocketmq.consumer.instanceName}")
    private String instanceName;
    @Value("${rocketmq.producer.sendMsgTimeout}")
    private int sendMsgTimeout;
    @Value("${rocketmq.producer.maxMessageSize}")
    private int maxMessageSize;
    @Value("${rocketmq.producer.compressOver}")
    private int compressOver;
    @Value("${rocketmq.topic}")
    private String topic;
    @Value("${rocketmq.tag}")
    private String tag;

    @Bean
    public DefaultMQPushConsumer getRocketMQConsumer() {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(this.groupName);
        consumer.setNamesrvAddr(this.namesrvAddr);
        consumer.setInstanceName(this.instanceName);
        consumer.setConsumeMessageBatchMaxSize(1);
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
      /*  consumer.setConsumeConcurrentlyMaxSpan(2000);  //单队列并行消费最大跨度,用于流控
        consumer.setPullThresholdForQueue(1000);       // 一个queue最大消费的消息个数,用于流控
        consumer.setPullInterval(1000);                //消息拉取时间间隔,默认为0,即拉完一次立马拉第二次,单位毫秒
        consumer.setMessageModel(MessageModel.CLUSTERING);  //消费模式,集群消费*/


        try {
            consumer.subscribe(this.topic, tag);
            consumer.registerMessageListener((MessageListenerConcurrently) (msgList, consumeConcurrentlyContext) -> {
                try {
                    MessageExt msg = null;
                    for (MessageExt aMsgList : msgList) {
                        msg = aMsgList;

                        System.out.println("收到MQ消息:"+new String(msg.getBody()));
                    }

                } catch (JSONException e) {
                    System.out.println(e);
                }

                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            });
            consumer.start();
            System.out.println("已启动Conusmer【gruop:" + this.groupName + ",instance:" + this.instanceName
                    + "】,监听TOPIC-{" + this.topic + "},tag-{" + this.tag + "}");
        } catch (MQClientException e) {
            System.out.println(e);
        }
        return consumer;
    }
}

producter项目中,同样创建配置类,用于创建Producter

@Configuration
public class SpringConfig {

    @Value("${rocketmq.consumer.groupName}")
    private String groupName;
    @Value("${rocketmq.consumer.namesrvAddr}")
    private String namesrvAddr;
    @Value("${rocketmq.consumer.instanceName}")
    private String instanceName;
    @Value("${rocketmq.producer.sendMsgTimeout}")
    private int sendMsgTimeout;
    @Value("${rocketmq.producer.maxMessageSize}")
    private int maxMessageSize;
    @Value("${rocketmq.producer.compressOver}")
    private int compressOver;
    @Value("${rocketmq.topic}")
    private String topic;
    @Value("${rocketmq.tag}")
    private String tag;


    @Bean
    public DefaultMQProducer getRocketMQProducer() {
        DefaultMQProducer producer;
        producer = new DefaultMQProducer(this.groupName);
        producer.setNamesrvAddr(this.namesrvAddr);
        producer.setInstanceName(instanceName);
        producer.setSendMsgTimeout(this.sendMsgTimeout);
        producer.setCompressMsgBodyOverHowmuch(this.compressOver);
        producer.setMaxMessageSize(this.maxMessageSize);

        try {
            System.out.println("Producer start...");
            producer.start();

        } catch (Exception e) {
            System.out.println(e);
        }
        return producer;
    }

二、测试

生产者发送消息的三种方式

发送方式

发送TPS

发送结果反馈

可靠性

同步发送



不丢失

异步发送



不丢失

单向发送

最快


可能丢失

将在生产者项目中添加test进行测试

在test目录下对应位置创建或修改已有测试类,添加自动注入生产者实例

@Autowired
DefaultMQProducer producer;

1.同步发送

* 可靠同步发送
* 含义:
*   同步发送是指消息发送方发出数据后,会在收到接收方发回响应之后才发下一个数据包的通讯方式
* 方式:
*   调用DefaultMQProducer的send方法
* 应用场景:
*   重要消息通知、短信通知等
@Test
void ReliableSynchronousT() throws MQBrokerException, RemotingException, InterruptedException, MQClientException {
    for (int i = 0; i < 10; i++)
    {
         final  int index = i;
         Message msg = new Message("test-demo" /* Topic */,
                                      "111" /* Tag */,
                                      ("hello rocketMq" + index).getBytes(StandardCharsets.UTF_8) /* Message body */
         );
         SendResult sendResult = producer.send(msg);
         System.out.println(sendResult.getSendStatus() + "  " + i);
    }
}

启动测试

生产者窗口,发现消息是一条一条接着发送

RocketMQTemplate 发送消息 添加tag 和key_spring

 在消费者窗口查看

RocketMQTemplate 发送消息 添加tag 和key_消息队列_02

 

2.异步发送

/*
    * 异步发送
    * 含义:
    *   异步发送是指消息发送方发出数据后,不等待接收方响应,直接发送下一个数据包
    * 方式:
    *   用户调用异步发送接口SendCallback
    * 应用:
    *   时间敏感场景
    * */
@Test
    void AsyncT() throws RemotingException, InterruptedException, MQClientException {
        producer.setRetryTimesWhenSendAsyncFailed(0);
        CountDownLatch countDownLatch = new CountDownLatch(100);
        for (int i = 0; i < 10; i++)
        {
            final  int index = i;
            Message msg = new Message("test-demo" /* Topic */,
                    "111" /* Tag */,
                    ("hello rocketMq by Async" + index).getBytes(StandardCharsets.UTF_8) /* Message body */
            );
            producer.send(msg, new SendCallback() {
                @Override
                public void onSuccess(SendResult sendResult) {
                    System.out.printf("发送:" + index);
                }

                @Override
                public void onException(Throwable throwable) {
                    System.out.printf("发送:" + index + "失败 " + throwable);
                }
            });
            //添加线程延迟,否则发送失败
            countDownLatch.await(1, TimeUnit.SECONDS);
        }
    }

生产者界面

RocketMQTemplate 发送消息 添加tag 和key_System_03

 消费者

RocketMQTemplate 发送消息 添加tag 和key_Test_04

 3.单向发送

/*
    * 单向发送
    * 含义:
    *   单向发送 发送方只负责发送消息,不等待服务器回应,没有相应回调触发
    *   发送消息时间短,通常为微妙级别
    * 方式:
    *   sendOneway方法
    * 应用:
    *   一定可靠性场景,如日志收集
    * */
@Test
    void OneWayT() throws RemotingException, InterruptedException, MQClientException {
        for (int i = 0; i < 10; i++)
        {
            final  int index = i;
            Message msg = new Message("test-demo" /* Topic */,
                    "111" /* Tag */,
                    ("hello rocketMq by OneWay" + index).getBytes(StandardCharsets.UTF_8) /* Message body */
            );
           producer.sendOneway(msg);

        }
    }

生产者无输出

RocketMQTemplate 发送消息 添加tag 和key_Test_05

 消费者

RocketMQTemplate 发送消息 添加tag 和key_Test_06