RocketMQ 使用

目录

前言

工作流程

入门使用

Producer

Consumer

同步发送

异步消息

单向消息

顺序消息

局部顺序

全局顺序

乱序消费

广播消息

延迟消息

批量消息

过滤消息

事务消息

整合SpringBoot

前言

RocketMQ的由4部分组成:NameServers,Broker,Producer,Consumer

  • NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步
  • Broker具体存储topic、消息的组件,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
  • Producer消息生产者,与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Broker中的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
  • Consumer消息消费者,与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向Master拉取消息时,Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读I/O),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。
     

工作流程

  • 启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
  • Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
    收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
  • Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
  • Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。

入门使用

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

Producer

package com.lb.base;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;

import java.nio.charset.StandardCharsets;

public class BaseProducer {
    public static void main(String[] args) throws Exception {
        //1.创建生产者
        DefaultMQProducer producer = new DefaultMQProducer("my-producer-group1");
        //2.生产者指定nameserver的地址
        producer.setNamesrvAddr("192.168.99.100:9876");
        //3.启动生产者
        producer.start();
        //4.创建消息
        for (int i = 0; i < 10; i++) {
            Message message =
                    new Message("Mytopic1", "TagA",
                            ("hello rocketmq" + i).getBytes(StandardCharsets.UTF_8));
        //5.发送方法
            SendResult sendResult = producer.send(message);
            System.out.println(sendResult);
        }
        //6.关闭生产者
        producer.shutdown();
    }
}

结果:

RocketMQLog:WARN No appenders could be found for logger (io.netty.util.internal.PlatformDependent0).
RocketMQLog:WARN Please initialize the logger system properly.
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885868AE0000, offsetMsgId=C0A8636400002A9F0000000000000000, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=1], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC8858690F0001, offsetMsgId=C0A8636400002A9F00000000000000B0, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=2], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885869150002, offsetMsgId=C0A8636400002A9F0000000000000160, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=3], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885869220003, offsetMsgId=C0A8636400002A9F0000000000000210, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=0], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885869260004, offsetMsgId=C0A8636400002A9F00000000000002C0, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=1], queueOffset=1]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC8858692B0005, offsetMsgId=C0A8636400002A9F0000000000000370, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=2], queueOffset=1]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC8858692F0006, offsetMsgId=C0A8636400002A9F0000000000000420, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=3], queueOffset=1]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885869390007, offsetMsgId=C0A8636400002A9F00000000000004D0, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=0], queueOffset=1]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC8858693C0008, offsetMsgId=C0A8636400002A9F0000000000000580, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=1], queueOffset=2]
SendResult [sendStatus=SEND_OK, msgId=C0A80066158414DAD5DC885869410009, offsetMsgId=C0A8636400002A9F0000000000000630, messageQueue=MessageQueue [topic=Mytopic1, brokerName=broker-a, queueId=2], queueOffset=2]

Process finished with exit code 0

注意:

根据结果可以发现,一个队列默认创建四个队列用来存储消息,如果是集群状态每个broker都存在4个队列消息会分布在所有broker的所有队列上,我的rocketmq只启动了一个broker所以消息都在这个broker的4个队列里面。

当我们指明topic时,如果topic本身不存在,需要rocketmq帮我们创建主题,则需要配置文件开启

#是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true

Consumer

package com.lb.base;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.*;
import org.apache.rocketmq.common.message.MessageExt;

import java.nio.charset.StandardCharsets;
import java.util.List;

public class BaseConsumer {
    public static void main(String[] args) throws Exception {
        //1.创建消费者对象
        DefaultMQPushConsumer consumer =
                new DefaultMQPushConsumer("my-consumer-group1");
        //2.指明nameserver地址
        consumer.setNamesrvAddr("192.168.99.100:9876");
        //3.consumer订阅主题Mytopic1下的TagA标签的消息
        //参数2 subExpression代表过滤消息的表达式
        consumer.subscribe("Mytopic1", "TagA");
        //订阅主题Mytopic1下所有消息
//        consumer.subscribe("Mytopic1", "*");
        //4.创建一个监听器,当broker把消息推过来调用
        consumer.registerMessageListener(new MessageListenerConcurrently(){
            &#
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值