RocketMQ(三)RocketMQ消息发送

1 单生产者单消费者消息发送

1.1 新建maven项目

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

1.2 生产者

public class Producer {
    public static void main(String[] args) throws Exception {
        // 谁来发
        DefaultMQProducer producer = new DefaultMQProducer("group1");
        // 发给谁
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        // 消息主体
        Message msg = new Message("topic1", "hello rocketmq".getBytes("UTF-8"));
        // 获取结果
        SendResult result = producer.send(msg);
        System.out.println("返回结果:" + result);
        // 关闭连接
        producer.shutdown();
    }
}

在这里插入图片描述

1.3 消费者

public class Consumer {
    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
        consumer.setNamesrvAddr("localhost:9876");
        //3.设置接收消息对应的topic,对应的sub标签为任意
        consumer.subscribe("topic1","*");
        //3.开启监听,用于接收消息
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                //遍历消息
                for (MessageExt msg : list) {
                    System.out.println("收到消息:"+msg);
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.println("接受消息服务已经开启!");
    }
}

在这里插入图片描述

2 单生产者多消费者消息发送

单生产者产生的消息可以被同一个消费者消费,也可以被多个消费者消费

生产者发送十条消息

 for (int i = 0; i < 10; i++) {
     String message = "hello rocketmq" + i;
     Message msg = new Message("topic2", message.getBytes("UTF-8"));
     // 获取结果
     SendResult result = producer.send(msg);
     System.out.println("返回结果:" + result);
 }

消费者消费消息

允许多次启动
在这里插入图片描述

启动两个消费者,这个时候会出现每个消费者收到五个消息。(负载均衡模式:默认模式)

要想让生产者生产的消息每个消费者都全部获取,可以将负载均衡模式改为广播模式或
通过修改组名,每个消费者组名不同就可以全部获取

 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");

即集群模式下,同个主题对于不同组是“广播模式”,每个组都会消费同个消息;会重复消费;对于同个组是“集群模式”,每个消费者平坦消息,不会重复消费;

在这里插入图片描述

思考: Consumerl、2同组就要都收到全部10条消息?

消费模式默认是MessageModel.CLUSTERING
在这里插入图片描述

现在我把它设置为 BROADCASTING模式

consumer.setMessageModel(MessageModel.BROADCASTING);

3 消息类别

3.1 同步消息

一条消息发送并且接收到返回消息后才发送下一条消息,常用于类似于邮件发送、短信发送的场景

特征:即时性较强,重要的消息,且必须有回执的消息,例如短信,通知(转账成功)

3.2 异步消息

特征:即时性较弱,但需要有回执的消息,例如订单中的某些信息

下面是生产者异步发送的代码,producer.send(msg, sendCallback()) 是异步的,下面代码会先打印异步发送完成,再打印消息结果。因此之前写的producer.shutdown();要删掉,不然会先执行producer.shutdown();再执行异步方法,导致没有producer。

for (int i = 0; i < 10; i++) {
    String message = "hello rocketmq + 异步" + i;
    Message msg = new Message("topic3", message.getBytes("UTF-8"));
    producer.send(msg, new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
            System.out.println(sendResult);
        }

        @Override
        public void onException(Throwable throwable) {
            // 业务逻辑
            System.out.println(throwable);
        }
    });
    System.out.println("异步发送完成");
}

在这里插入图片描述

3.3 单向消息

特征:不需要有回执的消息,例如日志类消息

producer.sendOneway(message);

3.3 延时消息

特征:消息发送时并不直接发送到消息服务器,而是根据设定的等待时间到达,起到延时到达的缓冲作用

可以给每个消息设置延时

// 设置延迟时间为等级3
msg.setDelayTimeLevel(3);
SendResult sendResult = producer.send(msg);

目前支持的延时类型有:

在这里插入图片描述

3.4 批量消息

特征:一次发送多条消息,节约网络开销

生产者发送一次消息就要和nameServer建立连接,和broker建立连接,在真实环境中每秒可以发几万甚至几十万的消息,会造成连接过多系统性能下降。而批量发送就可以集中一次发送。

String msg = "hello rocketmq producer batch";
List<Message> messageList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
    Message message = new Message("topic4", msg.getBytes(StandardCharsets.UTF_8));
    messageList.add(message);
}
producer.send(messageList);

在这里插入图片描述

4 消息过滤

4.1 tag 过滤

在这里插入图片描述

4.2 sql过滤

使用 SQL 过滤, 需要在broker.conf文件中添加配置enablePropertyFilter=true
在这里插入图片描述

在生产者中追加属性

 Message msg = new Message("topic6", "tag3","hello rocketmq".getBytes("UTF-8"));
 // 给消息追加属性
 msg.putUserProperty("name", "zhangsan");
 msg.putUserProperty("age", "12");

在消费者过滤

consumer.subscribe("topic6", MessageSelector.bySql("age > 16"));

在这里插入图片描述

5 SpringBoot整合RocketMQ

5.1 项目搭建

5.1.1 依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-spring-boot-starter</artifactId>
        <version>2.2.1</version>
    </dependency>
</dependencies>
5.1.3 producer 服务搭建

yml文件

rocketmq:
  name-server: localhost:9876
  producer:
    group: group1
server:
  port: 8088

实现

@Autowired
private RocketMQTemplate rocketMQTemplate;

@GetMapping("send")
public String send() {
    User user = new User("cc", 19);
    rocketMQTemplate.convertAndSend("topic10", user);
    return "success";
}
5.1.3 consumer 服务搭建

yml文件

server:
  port: 8089
rocketmq:
  name-server: localhost:9876
  producer:
    group: group1

servie监听

@Service
@RocketMQMessageListener(topic = "topic10", consumerGroup = "group1")
public class ConsumerService implements RocketMQListener<User> {
    @Override
    public void onMessage(User user) {
        System.out.println(user);
    }
}

5.2 其他功能

5.2.1 消息类别
@GetMapping("send")
public String send() {
    User user = new User("cc", 19);
    rocketMQTemplate.convertAndSend("topic10", user);
    return "success";
}

@GetMapping("syncSend")
public String syncSend() {
    User user = new User("cc", 19);
    SendResult result = rocketMQTemplate.syncSend("topic10", user);
    return "同步发送成功";
}

@GetMapping("asyncSend")
public String asyncSend() {
    User user = new User("cc", 19);
    rocketMQTemplate.asyncSend("topic10", user, new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
            System.out.println(sendResult);
        }

        @Override
        public void onException(Throwable throwable) {
            System.out.println(throwable);
        }
    }, 1000);
    return "异步发送成功";
}

@GetMapping("sendOneWay")
public String sendOneWay() {
    User user = new User("cc", 19);
    rocketMQTemplate.sendOneWay("topic10", user);
    return "单向消息发送成功";
}

@GetMapping("sendDelayLevel")
public String sendDelayLevel() {
    User user = new User("cc", 19);
    rocketMQTemplate.syncSend("topic10", MessageBuilder.withPayload(user).build(), 2000, 3);
    return "延时消息发送成功";
}

@GetMapping("sendMatch")
public String sendMatch() {
    List<User> users= new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        User user = new User("小" + i, i);
        users.add(user);
    }
    rocketMQTemplate.syncSend("topic10", users, 1000);
    return "批量发送成功";
}
5.2.2 消息过滤
5.2.2.1 tag过滤
@RocketMQMessageListener(topic = "topic10", consumerGroup = "group1", selectorExpression = "tag1 || tag2")
5.2.2.2 sql过滤
@RocketMQMessageListener(topic = "topic10", consumerGroup = "group1", selectorType = SelectorType.SQL92,
        selectorExpression = "age >= 18", messageModel = MessageModel.BROADCASTING)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RocketMQ发送消息的主要步骤如下: 1. 验证消息:在发送消息之前,会对消息进行验证,包括检查消息的合法性和完整性等方面。 2. 查找路由:RocketMQ会根据消息的主题(topic)来查找路由信息,确定消息应该发送到哪个消息队列。 3. 消息发送:根据路由信息,将消息发送到相应的消息队列。RocketMQ提供了发送方式: - 同步发送:使用DefaultMQProducer的send方法进行同步发送,会等待消息发送完成并返回发送结果。 - 异步发送:使用DefaultMQProducer的send方法进行异步发送,可以设置回调函数,在消息发送完成后执行回调函数。 - 单向发送:使用DefaultMQProducer的sendOneway方法进行单向发送,不关心发送结果,不等待响应。 在RocketMQ的topic创建机制中,一个topic对应有多个消息队列。在发送消息时,RocketMQ会根据消息的主题(topic)来选择一个消息队列进行发送。选择消息队列的算法可以是根据消息的key进行哈希计算,或者使用轮询的方式等。 如果在发送消息时遇到了故障的broker,RocketMQ会通过以下方式规避故障: 1. 客户端会定期从NameServer获取最新的broker列表,如果发现有broker宕机,会将宕机的broker从列表中移除。 2. 如果发送消息时选择的消息队列所在的broker宕机了,RocketMQ会尝试选择另一个可用的broker进行消息发送。 3. 如果所有的broker都宕机了,RocketMQ会等待一段时间后重新尝试发送消息,直到有可用的broker为止。 综上所述,RocketMQ发送消息的流程包括验证消息、查找路由和消息发送,而在选择消息队列时会根据消息的主题进行选择。在遇到故障broker时,RocketMQ会通过更新broker列表和选择可用的broker来规避故障。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值