初时RocketMQ

83 阅读4分钟

目录

主要角色

image.png

broker

  • Broker面向producer和consumer接受和发送消息
  • 向nameserver提交自己的信息
  • 是消息中间件的消息存储、转发服务器。
  • 每个Broker节点,在启动时,都会遍历NameServer列表,与每个NameServer建立长连接,注册自己的信息,之后定时上报。

broker集群

  • Broker高可用,可以配成Master/Slave结构,Master可写可读,Slave只可以读,Master将写入的数据同步给Slave。

    • 一个Master可以对应多个Slave,但是一个Slave只能对应一个Master
    • Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义BrokerId为0表示Master,非0表示Slave
  • Master多机负载,可以部署多个broker

    • 每个Broker与nameserver集群中的所有节点建立长连接,定时注册Topic信息到所有nameserver。

producer

  • 消息的生产者
  • 通过集群中的其中一个节点(随机选择)建立长连接,获得Topic的路由信息,包括Topic下面有哪些Queue,这些Queue分布在哪些Broker上等
  • 接下来向提供Topic服务的Master建立长连接,且定时向Master发送心跳

consumer

消息的消费者,通过NameServer集群获得Topic的路由信息,连接到对应的Broker上消费消息。

注意,由于Master和Slave都可以读取消息,因此Consumer会与Master和Slave都建立连接。

nameserver

底层由netty实现,提供了路由管理、服务注册、服务发现的功能,是一个无状态节点

nameserver是服务发现者,集群中各个角色(producer、broker、consumer等)都需要定时想nameserver上报自己的状态,以便互相发现彼此,超时不上报的话,nameserver会把它从列表中剔除

nameserver可以部署多个,当多个nameserver存在的时候,其他角色同时向他们上报信息,以保证高可用,

NameServer集群间互不通信,没有主备的概念

nameserver内存式存储,nameserver中的broker、topic等信息默认不会持久化

RocketMQ Hello World级别Demo

首先就是导包

      <!-- rocketmq 因为我的服务器部署的是5.0.0的RocketMQ-client -->
      <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-client</artifactId>
        <version>5.0.0</version>
      </dependency>

之后我们就建两个类,生产者,消费者

首先是生产者

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
​
public class Producer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer defaultMQProducer = new DefaultMQProducer("llgp");
        //设置发送的服务器地址和端口
        defaultMQProducer.setNamesrvAddr("192.168.124.128:9876");
        defaultMQProducer.start();
        //第一个参数是发送的主题,第二个是消息体需要转换成字节
        Message msg = new Message("mytopic","llgp".getBytes());
        defaultMQProducer.send(msg);
        
    }
}

此时我们可以进行测试,直接运行main方法,去可视化页面进行查看

image.png 刚刚创建的主题已经出现了

创建消费者

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
​
import java.util.List;
​
​
public class Consumer {
    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer("llcsm");
        defaultMQPushConsumer.setNamesrvAddr("192.168.124.128:9876");
        //订阅主题,一个消费者只能订阅一个主题
        //第一个是主题,第二个参数是过滤条件
        defaultMQPushConsumer.subscribe("mytopic","*");
        //监听我们的队列,获取消息
        defaultMQPushConsumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                for (MessageExt msg : list){
                    System.out.println(new String(msg.getBody()));
                }
                //一个消息只能被一个consumer消费
                //通过返回状态,修改message的状态
                //ack用来确认的
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
​
        defaultMQPushConsumer.start();
​
    }
}

运行消费者

image.png

此时我们重新运行我们的生产者,我们的这边消费者会持续打印

在控制台我们也能看到相应的消息

image.png

image.png

image.png

image.png

,此时还有一个问题就是我们生产者一直在运行没有关闭

public class Producer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer defaultMQProducer = new DefaultMQProducer("llgp");
        //设置发送的服务器地址和端口
        defaultMQProducer.setNamesrvAddr("192.168.124.128:9876");
        defaultMQProducer.start();
        //第一个参数是发送的主题,第二个是消息体需要转换成字节
        Message msg = new Message("mytopic","llgp".getBytes());
        //同步消息发送,返回的消息是消费者那边return的
        SendResult sendResult = defaultMQProducer.send(msg);
​
        System.out.println(sendResult);
        //停机
        defaultMQProducer.shutdown();
    }
}

image.png

在生产者关闭之后,我们在可视化页面也找不到生产者

以上就是RocketMQ入门级别的代码了,当然还有很多用法,比如TAG,SQL过滤种种还是需要自己的去摸索的了,我把一个简单的例子放在这里了,密码543r