RocketMQ笔记(二)SpringBoot整合RocketMQ发送异步消息

一、简介

  RocketMQ 的消息同步发送我们也演示过了,本文主要是简单的讲解异步发送。

1.1、概念

  异步发送指的是生产者在发送消息后,直接返回,不需要等待Broker的响应。消息发送的结果通过指定的回调接口进行异步通知。异步发送的优缺点如下:

优点:

  • 无需等待Broker响应,减少了发送延迟
  • 吞吐量相对较高,适合于发送端吞吐量高的场景

缺点:

  • 发送可靠性相对同步发送模式略低,无法立即感知发送结果
  • 需要通过回调接口获取发送结果,增加了一些代码复杂性

1.2、场景

  异步发送对消息可靠性传输要求不是特别高的场景,允许存在少量消息丢失情况,发送端吞吐量很高,需要尽量减少发送延迟的场景,如日志收集等

二、Maven依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rocketmq</artifactId>
        <groupId>com.alian</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>02-send-async-message</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alian</groupId>
            <artifactId>common-rocketmq-dto</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

  父工程已经在我上一篇文章里,通用公共包也在我上一篇文章里有说明,包括消费者。具体参考:RocketMQ笔记(一)SpringBoot整合RocketMQ发送同步消息

三、application配置

application.properties

server.port=8002

# rocketmq地址
rocketmq.name-server=192.168.0.234:9876
# 默认的生产者组
rocketmq.producer.group=async_group
# 发送同步消息超时时间
rocketmq.producer.send-message-timeout=3000
# 用于设置在消息发送失败后,生产者是否尝试切换到下一个服务器。设置为 true 表示启用,在发送失败时尝试切换到下一个服务器
rocketmq.producer.retry-next-server=true
# 用于指定消息发送失败时的重试次数
rocketmq.producer.retry-times-when-send-failed=3
# 设置消息压缩的阈值,为0表示禁用消息体的压缩
rocketmq.producer.compress-message-body-threshold=0

四、生产者

  上一篇文章中,我们演示了不同类型的消息发送,实际中还是以json形式发送的居多,所以本文异步发送就主要说异步发送json消息。

4.1、普通消息

  在 RocketMQ 中,RocketMQTemplateasyncSend方法。它允许你发送消息而不必等待发送结果,而是在发送完毕后执行一个回调函数以处理发送结果。这个回调函数是通过 SendCallback 接口来定义的,通常包含两个方法:

  • onSuccess(SendResult sendResult):当消息发送成功时调用这个方法,sendResult 参数包含了发送消息的结果信息,如消息 ID 等。
  • onException(Throwable throwable):当消息发送失败时调用这个方法,throwable 参数包含了发送失败的异常信息。

SendJsonMessageTest1.java

@Slf4j
@SpringBootTest
public class SendJsonMessageTest1 {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Test
    public void asyncSendJsonMessage() {
        String topic = "json_message_topic";
        JSONObject json = new JSONObject();
        json.put("name", "Alian");
        json.put("age", "28");
        json.put("hobby", "java");
        rocketMQTemplate.asyncSend(topic, json, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                // 异步发送成功的回调逻辑
                log.info("异步消息发送json信息成功: " + sendResult);
            }

            @Override
            public void onException(Throwable e) {
                // 异步发送失败的回调逻辑
                log.info("异步消息发送json信息失败: " + e.getMessage());
            }
        });
    }

    @AfterEach
    public void waiting() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4.2、构建发送

SendJsonMessageTest2.java

@Slf4j
@SpringBootTest
public class SendJsonMessageTest2 {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Test
    public void asyncSendJsonMessageWithBuilder() {
        String topic = "json_message_topic";
        JSONObject json = new JSONObject();
        json.put("name", "Alian");
        json.put("age", "28");
        json.put("hobby", "java");
        Message<JSONObject> msg = MessageBuilder.withPayload(json)
                // 设置消息类型
                .setHeader(MessageHeaders.CONTENT_TYPE, "application/json")
                .build();
        rocketMQTemplate.asyncSend(topic, msg, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                // 异步发送成功的回调逻辑
                log.info("异步消息发送json信息成功: " + sendResult);
            }

            @Override
            public void onException(Throwable e) {
                // 异步发送失败的回调逻辑
                log.info("异步消息发送json信息失败: " + e.getMessage());
            }
        });
    }

    @AfterEach
    public void waiting() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4.3、自定义回调

  看到前面写代码结构比较繁琐,我们可以简化下回调方法,只需要实现接口SendCallback

package org.apache.rocketmq.client.producer;

public interface SendCallback {
    void onSuccess(SendResult var1);

    void onException(Throwable var1);
}

然后实现成功和失败的方法即可,具体如下:

JsonSendCallback.java

package com.alian.async;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;

@Slf4j
public class JsonSendCallback implements SendCallback {
    @Override
    public void onSuccess(SendResult sendResult) {
        // 异步发送成功的回调逻辑
        log.info("异步消息发送JSON消息成功: " + sendResult);
    }

    @Override
    public void onException(Throwable e) {
        // 异步发送失败的回调逻辑
        log.info("异步消息发送JSON消息失败: " + e.getMessage());
    }
}

此时我们调用的方法就可以改造如下:

SendJsonMessageTest3.java

@Slf4j
@SpringBootTest
public class SendJsonMessageTest3 {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Test
    public void asyncSendJsonMessageWithBuilderMyCallback() {
        String topic = "json_message_topic";
        JSONObject json = new JSONObject();
        json.put("name", "Alian");
        json.put("age", "28");
        json.put("hobby", "java");
        Message<JSONObject> msg = MessageBuilder.withPayload(json)
                // 设置消息类型
                .setHeader(MessageHeaders.CONTENT_TYPE, "application/json")
                .build();
        // 3秒发送超时,延迟级别为3(也就是要10秒后才能被消费者消费)
        rocketMQTemplate.asyncSend(topic, msg, new JsonSendCallback());
    }

    @AfterEach
    public void waiting() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4.4、异步延迟发送

SendJsonMessageTest4

@Slf4j
@SpringBootTest
public class SendJsonMessageTest4 {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Test
    public void asyncSendJsonMessageWithBuilderMyCallback() {
        String topic = "json_message_topic";
        JSONObject json = new JSONObject();
        json.put("name", "Alian");
        json.put("age", "28");
        json.put("hobby", "java");
        Message<JSONObject> msg = MessageBuilder.withPayload(json)
                // 设置消息类型
                .setHeader(MessageHeaders.CONTENT_TYPE, "application/json")
                .build();
        // 3秒发送超时,延迟级别为3(也就是要10秒后才能被消费者消费)
        rocketMQTemplate.asyncSend(topic, msg, new JsonSendCallback(),3000,3);
    }

    @AfterEach
    public void waiting() {
        try {
            Thread.sleep(20000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3秒发送超时,延迟级别为3(也就是要10秒后才能被消费者消费),看到这里了相信大家都看到一段代码了

    @AfterEach
    public void waiting() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

  这个是测试生命周期的注解,我这里休眠了3秒,因为是单元测试,异步发送时,调用完发送程序就结束了,就没法收到异步回调了,所有这里采用了休眠的方式,具体休眠时间大家可以自行调整。

  关于消费者不用做任何改变和我上文中一样。

五、运行结果

5.1、普通消息

json消费者接收到的消息: {"name":"Alian","age":"28","hobby":"java"}

异步消息发送json信息成功: SendResult [sendStatus=SEND_OK, msgId=7F000001373818B4AAC235FD45C70000, offsetMsgId=C0A800EA00002A9F00000000000003CD, messageQueue=MessageQueue [topic=json_message_topic, brokerName=broker-a, queueId=1], queueOffset=1]

5.2、构建对象再发送

json消费者接收到的消息: {"name":"Alian","age":"28","hobby":"java"}

异步消息发送json信息成功: SendResult [sendStatus=SEND_OK, msgId=7F000001402818B4AAC235FE628C0000, offsetMsgId=C0A800EA00002A9F00000000000004F7, messageQueue=MessageQueue [topic=json_message_topic, brokerName=broker-a, queueId=0], queueOffset=0]

5.3、自定义回调

json消费者接收到的消息: {"name":"Alian","age":"28","hobby":"java"}

异步消息发送JSON消息成功: SendResult [sendStatus=SEND_OK, msgId=7F00000113C818B4AAC235FEEB900000, offsetMsgId=C0A800EA00002A9F0000000000000621, messageQueue=MessageQueue [topic=json_message_topic, brokerName=broker-a, queueId=0], queueOffset=1]

5.4、异步延迟

2024-03-11 11:43:15.289  INFO 15224 --- [ublicExecutor_1] com.alian.async.JsonSendCallback         : 异步消息发送JSON消息成功: SendResult [sendStatus=SEND_OK, msgId=7F0000013B7818B4AAC2360371360000, offsetMsgId=C0A800EA00002A9F000000000000074B, messageQueue=MessageQueue [topic=json_message_topic, brokerName=broker-a, queueId=1], queueOffset=0]

2024-03-11 11:43:25.297  INFO 9232 --- [NT_GROUP_JSON_4] c.alian.concurrent.JsonMessageConsumer   : json消费者接收到的消息: {"name":"Alian","age":"28","hobby":"java"}

从上面时间可以看到消费者等发送完到消费中间有10秒的延迟。

  一般来说,同步发送模式用于可靠性要求较高的场合,异步发送模式则更多用于对吞吐量和延迟有较高要求的场合。在实际应用中,可以根据具体的业务场景来选择合适的发送方式。如果对消息可靠性要求不是非常高,且发送端吞吐量较大,建议采用异步发送模式,以提高消息发送的性能和系统的吞吐能力。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供有关RocketMQ的一些笔记。这是一个开源的分布式消息中间件系统,由阿里巴巴集团开发和维护。RocketMQ具有高可用性、高吞吐量和可伸缩性,适用于构建实时数据处理、大规模消息系统和事件驱动架构等场景。 下面是一些关键点和要点: 1. 架构:RocketMQ采用了主题(Topic)和队列(Queue)的概念。主题是消息的逻辑分类,队列则是主题的物理分区。每个队列都有自己的消费者组来处理消息。 2. 消息模型:RocketMQ支持两种消息模型:发布/订阅模型和点对点模型。在发布/订阅模型中,消息发送到主题,然后订阅者从主题订阅消息。在点对点模型中,消息发送到队列,然后消费者从队列中消费消息。 3. 可靠性:RocketMQ提供了多种机制来确保消息的可靠性传输,包括同步发送异步发送和定时发送。还支持消息顺序发送和顺序消费。 4. 高可用性:RocketMQ通过主从复制和Broker集群来实现高可用性。每个主题的队列都可以在多个Broker之间进行复制,以实现数据冗余和容错。 5. 扩展性:RocketMQ可以通过添加更多的Broker节点来扩展系统容量和吞吐量。还支持动态扩展和缩减Broker集群。 6. 消息过滤:RocketMQ支持基于Tag或SQL表达式的消息过滤,以便订阅者只接收感兴趣的消息。 这只是RocketMQ的一些基本信息,还有很多其他特性和概念,如事务消息消息轨迹、延迟消息等。如果您对RocketMQ有进一步的疑问,请随时提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值