Rocketmq

一、Linux安装Rocketmq

1、linux安装jdk

由于Rocketmq使用java写的,所以运行环境需要jdk

第一步:将文件jdk-8u212-linux-x64.tar.gz(jdk)上传到 /root 目录

第二步:执行解压命令

# 将jdk解压到 /usr/local/ 目录
tar -xf jdk-8u212-linux-x64.tar.gz -C /usr/local/

# 切换到 /usr/local/ 目录, 显示列表, 查看解压缩的jdk目录
cd /usr/local
ll

第三步:配置环境变量

修改 /etc/profile 配置文件, 配置环境变量

vim /etc/profile

# 在文件末尾添加以下内容:

export JAVA_HOME=/usr/local/jdk1.8.0_212
export PATH=$JAVA_HOME/bin:$PATH


修改完后, 让环境变量立即生效

source /etc/profile

第四步:验证

java -version

----------------------------------------------------------------
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)


javac -version

---------------
javac 1.8.0_212


 

 2、linux安装Rocketmq

 第一步:下载 rocketmq 二进制文件

wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip 

 第二步:解压缩 rocketmq 

将 rocketmq 解压到 /usr/local/ 目录

unzip rocketmq-all-4.7.0-bin-release.zip -d /usr/local/

# 修改一下文件夹名,改成 rocketmq 方便使用
mv /usr/local/rocketmq-all-4.7.0-bin-release /usr/local/rocketmq

第三步:配置环境变量 ROCKETMQ_HOME 和 PATH

为了后续操作方便可以配置环境变量,之后在任意位置都可以执行rocketmq的操作命令。

vim /etc/profile

# 在文件末尾添加以下内容:

export ROCKETMQ_HOME=/usr/local/rocketmq
export PATH=$ROCKETMQ_HOME/bin:$PATH

修改完后, 让环境变量立即生效

source /etc/profile

第四步:减小 rocketmq 使用的内存
rocketmq需要启动两个服务: name server 和 broker, name server 默认配置JVM使用的内存是4g, broker默认配置JVM使用的内存是8g.

开发环境中如果内存不足, 服务可能会无法启动, 可以通过降低两个服务的内存, 使服务可以正常启动, 也可以节省内存.

修改 name server 内存改为 256m
 

cd /usr/local/rocketmq/

# 编辑 bin/runserver.sh
vim bin/runserver.sh

# 找到文件中下面这一行:
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

# 将 -Xms4g -Xmx4g -Xmn2g 修改为 -Xms256m -Xmx256m -Xmn128m
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

 修改 broker 内存改为 256m

# 编辑 bin/runbroker.sh
vim bin/runbroker.sh

# 找到文件中下面这一行:
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"

# 将 -Xms8g -Xmx8g -Xmn4g 修改为 -Xms256m -Xmx256m -Xmn128m
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m"

第五步,启动 rocketmq

先启动 name server

# 进入 rocketmq 目录
cd /usr/local/rocketmq/

# 启动 name server
nohup sh bin/mqnamesrv &

# 查看运行日志, 看到"The Name Server boot success."表示启动成功
tail -f ~/logs/rocketmqlogs/namesrv.log

再启动 broker

# 启动 broker, 连接name server: localhost:9876
nohup sh bin/mqbroker -n localhost:9876 &

# 查看运行日志, 看到"The broker[......:10911] boot success."表示启动成功
tail -f ~/logs/rocketmqlogs/broker.log 

第六步. 关闭防火墙

rocketmq的通信会用到多个端口, 为了方便测试我们关闭防火墙

# 关闭防火墙
systemctl stop firewalld.service

# 禁止防火墙开机启动
systemctl disable firewalld.service

 第七步:测试

运行测试, 启动生产者发送消息, 启动消费者接收消息
 

# 通过环境变量, 告诉客户端程序name server的地址
export NAMESRV_ADDR=localhost:9876

# 启动生产者来测试发送消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

# 启动消费者来测试接收消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

3、RocketMQ 的关闭命令

关闭 broker

mqshutdown broker

关闭 nameserver

mqshutdown namesrv

 4、收发消息出现超时问题

cd /usr/local/rocketmq/

vim conf/broker.conf

末尾添加
brokerIP1=192.168.64.141

关闭 broker 服务
mqshutdown broker

重新使用 broker.conf 配置启动 broker
nohup sh bin/mqbroker -n localhost:9876 -c conf/broker.conf &

二、Linux安装Rocketmq的管理界面

(57条消息) RocketMQ (一) 安装_扎瓦江石的博客-CSDN博客

1、下载地址

在开源项目 rocketmq-dashboard 中提供了rocketmq 的管理界面: 地址为: https://github.com/apache/rocketmq-dashboard

github 在国内访问缓慢, 也可以使用码云的镜像项目, 地址为: https://gitee.com/mirrors_apache/rocketmq-dashboard
 

2、运行启动管理界面

打包的 jar 文件在 target 目录, 进入目录执行jar文件

# 进入 target 目录
cd target

# 运行管理界面
nohup java -jar rocketmq-console-ng-1.0.1.jar --server.port=8080 --rocketmq.config.namesrvAddr=localhost:9876 &

3、运行启动管理界面

http://192.168.64.141:8080

rocketmq

三、 双主双从同步复制集群方案

RocketMQ (二) 双主双从同步复制集群方案_wanght笔记-CSDN博客

四、基本原理

在管理界面中新建主题Topic1,这里把写队列读队列的数量都设置成3。

Rocketmq_第1张图片

 Topic1 主题,并创建了3写3读队列 

Rocketmq_第2张图片

perm 参数的含义 

perm 参数是设置队列的读写权限,下面表格列出了可配置的值及其含义:

取值 含义
6 同时开启读写
4 禁写
2 禁读

Topic 收发消息原理 

Rocketmq_第3张图片

生产者的负载均衡

Rocketmq_第4张图片

 生产者以轮询的方式向所有写队列发送消息,这些队列可能会分布在多个broker实例上。

消费者的负载均衡

一个 group 中的多个消费者,可以以负载均衡的方式来接收消息。

读取队列被均匀分配给这些消费者,它们从指定的队列来接收消息。队列的分配可以采用不同的策略,这里简略介绍以下三种策略:

1、AllocateMessageQueueAveragely 平均分配

这是默认策略,它是这样分配队列的:

Rocketmq_第5张图片

2、 AllocateMessageQueueAveragelyByCircle 环形分配

如果使用环形分配,在消费者的代码中需要设置分配策略,代码如下:

consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueAveragelyByCircle());

Rocketmq_第6张图片

 3、AllocateMessageQueueConsistentHash 一致性哈希

如果使用一致性哈希算法进行分配,在消费者的代码中需要设置分配策略,代码如下:

consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueConsistentHash());

这种算法依靠一致性哈希算法,看当前消费者可以落到哪个虚拟节点,该虚拟节点对应哪个队列。

五、使用RocketMQ原生API收发消息代码样例

添加依赖

    
        
            org.apache.rocketmq
            rocketmq-client
            4.7.1
        

        
            org.apache.rocketmq
            rocketmq-store
            4.7.1
        

    

1、同步消息

Rocketmq_第7张图片

同步消息发送要保证强一致性,发到master的消息向slave复制后,才会向生产者发送反馈信息。

这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。

同步消息代码

生产者代码

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.util.Scanner;

//同步消息
public class Producer {

    public static void main(String[] args) throws MQBrokerException, RemotingException, InterruptedException, MQClientException {
        //1、新建生产者实例
        DefaultMQProducer p = new DefaultMQProducer("p1"); //参数为生产者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        p.setNamesrvAddr("192.168.64.141:9876");

        //3、启动(连接服务器)
        p.start();

        //4、发送消息
        while (true){
            System.out.println("请输入消息");
            String s = new Scanner(System.in).nextLine();

            //4.1、将要发送的消息封装到Message对象   import org.apache.rocketmq.common.message.Message;
            //参数一为注册名字,相当于一级标签,参数二(可加可不加)为二级标签,参数三为需要发送的消息,格式为byte数组
            Message msg = new Message("Topic1","Tap1",s.getBytes());

            //4.2、会得到一个反馈信息:发送到哪里,是否成功,等等)
            SendResult r =  p.send(msg);

            //打印反馈信息
            System.out.println(r);
        }
    }
}

消费者代码


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.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class Consumer {

    public static void main(String[] args) throws MQClientException {

        //1、新建消费者实例
        DefaultMQPushConsumer c = new DefaultMQPushConsumer("c1");//参数为消费者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        c.setNamesrvAddr("192.168.64.141:9876");

        //3、订阅消息(指定在哪接收消息)
        // *                        - 所有标签
        // Tag1 || Tag2 || Tag3     - 多种标签
        // Tag1                     - 一种标签
        c.subscribe("Topic1","Tap1");

        //4、设置处理消息的监听器
        c.setMessageListener(new MessageListenerConcurrently() {  //多个线程并发接收处理消息(同时接收处理多条消息)
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                for (MessageExt msg : msgs) {
                    String s = new String(msg.getBody());
                    System.out.println("收到消息:" + s);
                }

                //表示消息处理成功
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

                //有异常使用这个返回,告诉服务器重新发送,共计18次。并且请求间隔越来越长,最长间隔2小时。如果18次都处理失败,消息会进入死信队列。
                //return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
        });

        //5、启动(连接服务器)
        c.start();
    }
}

2、延时消息

消息发送到 Rocketmq 服务器后, 延迟一定时间再向消费者进行投递。

延时消息的使用场景:

比如电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。

延时消息和同步消息唯一的区别就是添加了一段延时代码

msg.setDelayTimeLevel(3);

延时对应关系表

级别 延时时长
1 1s
2 5s
3 10s
4 30s
5 1m
6 2m
7 3m
8 4m
9 5m
10 6m
11 7m
12 8m
13 9m
14 10m
15 20m
16 30m
17 1h
18 2h

延时代码

生产者代码


import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.util.Scanner;

//延迟消息
public class Producer {

    public static void main(String[] args) throws MQBrokerException, RemotingException, InterruptedException, MQClientException {
        //1、新建生产者实例
        DefaultMQProducer p = new DefaultMQProducer("p1"); //参数为生产者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        p.setNamesrvAddr("192.168.64.141:9876");

        //3、启动(连接服务器)
        p.start();

        //4、发送消息
        while (true){
            System.out.println("请输入消息");
            String s = new Scanner(System.in).nextLine();

            //4.1、将要发送的消息封装到Message对象   import org.apache.rocketmq.common.message.Message;
            //参数一为注册名字,相当于一级标签,参数二(可加可不加)为二级标签,参数三为需要发送的消息,格式为byte数组
            Message msg = new Message("Topic1","Tap1",s.getBytes());

            //4.2、设置延迟级别
            msg.setDelayTimeLevel(3);

            //4.3、会得到一个反馈信息:发送到哪里,是否成功,等等)
            SendResult r =  p.send(msg);
            
            //打印反馈信息
            System.out.println(r);

        }
    }
}
消费者代码


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.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class Consumer {

    public static void main(String[] args) throws MQClientException {

        //1、新建消费者实例
        DefaultMQPushConsumer c = new DefaultMQPushConsumer("c1");//参数为消费者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        c.setNamesrvAddr("192.168.64.141:9876");

        //3、订阅消息(指定在哪接收消息)
        // *                        - 所有标签
        // Tag1 || Tag2 || Tag3     - 多种标签
        // Tag1                     - 一种标签
        c.subscribe("Topic1","Tap1");

        //4、设置处理消息的监听器
        c.setMessageListener(new MessageListenerConcurrently() {  //多个线程并发接收处理消息(同时接收处理多条消息)
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                for (MessageExt msg : msgs) {
                    String s = new String(msg.getBody());
                    System.out.println("收到消息:" + s);
                }

                //表示消息处理成功
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

                //有异常使用这个返回,告诉服务器重新发送,共计18次。并且请求间隔越来越长,最长间隔2小时。如果18次都处理失败,消息会进入死信队列。
                //return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
        });

        //5、启动(连接服务器)
        c.start();
    }
}

3、顺序消息

Rocketmq_第8张图片

上图演示了 Rocketmq 顺序消息的基本原理:

  • 同一组有序的消息序列,会被发送到同一个队列,按照 FIFO 的方式进行处理
  • 一个队列只允许一个消费者线程接收消息,这样就保证消息按顺序被接收

生产者发送消息

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.util.List;
import java.util.Scanner;

//顺序消息
public class Producer {

    static String[] msgs = {
            "15103111039,创建",
            "15103111065,创建",
            "15103111039,付款",
            "15103117235,创建",
            "15103111065,付款",
            "15103117235,付款",
            "15103111065,完成",
            "15103111039,推送",
            "15103117235,完成",
            "15103111039,完成"
    };

    public static void main(String[] args) throws MQBrokerException, RemotingException, InterruptedException, MQClientException {

        //1、新建生产者实例
        DefaultMQProducer p = new DefaultMQProducer("p1"); //参数为生产者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        p.setNamesrvAddr("192.168.64.141:9876");

        //3、启动(连接服务器)
        p.start();

        //4、遍历数组发送消息
        for (String s : msgs){

            //4.1获取数组每个元素的id
            Long orderId =  Long.valueOf(s.split(",")[0]);

            //4.2、将要发送的消息封装到Message对象   import org.apache.rocketmq.common.message.Message;
            //参数一为注册名字,相当于一级标签,参数二(可加可不加)为二级标签,参数三为需要发送的消息,格式为byte数组
            Message msg = new Message("Topic2",s.getBytes());//服务器上没有Topic2,服务器上可以设置,默认可以自动创建

            //4.3、会得到一个反馈信息 参数一为要发送的消息,参数二为队列选择器,参数三为选择依据)
            SendResult r =  p.send(msg,
                    new MessageQueueSelector() {
                        @Override                          //参数一:队列信息,参数二:发送的消息对象,参数三:选择依据
                        public MessageQueue select(List list, Message message, Object o) {

                            Long orderId = (Long) o;
                            int index =(int) (orderId % list.size());
                            return list.get(index);
                         }
                     }, orderId);

            System.out.println(r);

        }
    }
}
消费者接收消息

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

import java.util.List;

public class Consumer {

    public static void main(String[] args) throws MQClientException {

        //1、新建消费者实例
        DefaultMQPushConsumer c = new DefaultMQPushConsumer("c2");//参数为消费者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        c.setNamesrvAddr("192.168.64.141:9876");

        //3、订阅消息(指定在哪接收消息)       //消费者没有设置标签,这里使用*号表示接收所有
        c.subscribe("Topic2","*");

        //4、设置处理消息的监听器,MessageListenerOrderly监听器可以按顺序处理消息
        c.setMessageListener(new MessageListenerOrderly() {
            @Override
            public ConsumeOrderlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {

                for (MessageExt msg : list){
                    String s = new String(msg.getBody());
                    System.out.println("收到:" + s);
                }
                return ConsumeOrderlyStatus.SUCCESS ;
            }
        });

        //5、启动
        c.start();
    }
}

4、事务消息 

RocketMQ 提供了可靠性消息,也叫事务消息。下面分析一下其原理。

事务消息的原理

事务

事务

下面来看 RocketMQ 的事务消息是如何来发送“可靠消息”的,只需要以下三步:

  1. 发送半消息(半消息不会发送给消费者)
  2. 执行本地事务
  3. 提交消息

 事务

事务

事务

完成事务消息发送后,消费者就可以以正常的方式来消费数据。

RocketMQ 的自动重发机制在绝大多数情况下,都可以保证消息被正确消费。

假如消息最终消费失败了,还可以由人工处理进行托底。

事务

上面分析的是正常情况下的执行流程。下面再来看两种错误情况:

  1. 事务执行失败时回滚消息
  2. 服务器无法得知消息状态时,需要主动回查消息状态

回滚:

事务

消息回查:

事务

事务

生产者发送消息

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.*;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.util.Scanner;

//事务消息
public class Producer {


    public static void main(String[] args) throws MQBrokerException, RemotingException, InterruptedException, MQClientException {

        //1、新建生产者实例
        TransactionMQProducer p = new TransactionMQProducer("p3"); //参数为生产者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        p.setNamesrvAddr("192.168.64.141:9876");

        //3、创建事务监听器
        p.setTransactionListener(new TransactionListener() {
            //3.1、执行本地事务
            @Override                                        //参数一为消息,参数二为业务数据参数
            public LocalTransactionState executeLocalTransaction(Message message, Object o) {

                System.out.println("半消息发送后,执行本地事务 ;业务数据参数为:" + o);

                if (true){  //测试未知状态
                    return LocalTransactionState.UNKNOW;
                }

                //返回状态,要么成功要么失败
                if (Math.random() < 0.5){
                    System.out.println("本地事务执行成功,提交消息");
                    //成功
                    return LocalTransactionState.COMMIT_MESSAGE;
                }else {
                    System.out.println("本地事务执行失败,回滚消息");
                    //失败
                    return LocalTransactionState.ROLLBACK_MESSAGE;
                }
                //表示是未知状态(实际业务中不可能出现这么模糊状态)
                //return LocalTransactionState.UNKNOW;
            }

            //3.2、处理Rocketmq服务器的事务回查操作
            @Override
            public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
                //可能原因
                //1、由于网络中断,上面事务无法通知服务器
                //2、上面的本地事务执行缓慢,超过一分钟

                System.out.println("Rocketmq服务器正在回查事务状态");

                //模拟网络中断,无法得到事务状态
                return LocalTransactionState.ROLLBACK_MESSAGE;
            }
        });

        //4、启动(连接服务器)
        p.start();

        //5、发送事务消息(先发送半消息),会触发一个监听器执行本地事务
        while (true){
            System.out.println("输入消息:");
            String s = new Scanner(System.in).nextLine();
            Message msg = new Message("Topic3",s.getBytes());
            //参数二为传递给监听器的业务数据参数
            p.sendMessageInTransaction(msg,"传递业务数据参数");
        }

    }
}

消费者接收消息

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.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class Consumer {

    public static void main(String[] args) throws MQClientException {

        //1、新建消费者实例
        DefaultMQPushConsumer c = new DefaultMQPushConsumer("c1");//参数为消费者组名字,无所谓,都可以

        //2、设置name server(注册中心)的地址
        c.setNamesrvAddr("192.168.64.141:9876");

        //3、订阅消息(指定在哪接收消息)
        c.subscribe("Topic3","Tap1");

        //4、设置处理消息的监听器
        c.setMessageListener(new MessageListenerConcurrently() {  //多个线程并发接收处理消息(同时接收处理多条消息)
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                for (MessageExt msg : msgs) {
                    String s = new String(msg.getBody());
                    System.out.println("收到消息:" + s);
                }

                //表示消息处理成功
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

                //有异常使用这个返回,告诉服务器重新发送,共计18次。并且请求间隔越来越长,最长间隔2小时。如果18次都处理失败,消息会进入死信队列。
                //return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
        });

        //5、启动(连接服务器)
        c.start();
    }
}

5、异步消息 

Rocketmq_第9张图片

master 收到消息后立即向生产者进行反馈。之后再以异步方式向 slave 复制消息。

异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。

你可能感兴趣的:(微服务,java)