rocketmq相关知识

1)RocketMQ搭建步骤

开发环境

  • 64位 centos7(虚拟机,1G内存)
  • 64位 jdk1.8
  • maven 3.5.0
  • Git
  • tomcat(用于启动rocketmq-console)
  • rocketmq 3.2.6(最好选择maven仓库中已有的版本,保持客户端依赖的jar包和服务器版本一致)
  • rocketmq-console

环境变量配置

vi /etc/profile 打开文件配置如下:

JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk

JRE_HOME=$JAVA_HOME/jre

CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib

M2_HOME=/usr/maven/

ROCKETMQ_HOME=/usr/rocketmq

PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$M2_HOME/bin:$ROCKETMQ_HOME/bin

export JAVA_HOME JRE_HOME CLASS_PATH M2_HOME ROCKETMQ_HOME PATH

export NAMESRV_ADDR=127.0.0.1:9876

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

source /etc/profile 使配置文件立即生效

防火墙配置

宿主机需要远程访问虚拟机的rocketmq服务和web服务,需要开放相关的端口号,简单粗暴的方式是直接关闭防火墙

service iptables stop 关闭防火墙

service iptables status 查看防火墙的状态

service iptables start 启动防火墙

  • 1
  • 2
  • 3

或者为了安全,只开放特定的端口号,如8080987610911等等,此处不再赘述。

安装、启动RocketMQ

1.下载和安装

cd /usr

wget https://github.com/alibaba/RocketMQ/releases/download/v3.2.6/alibaba-rocketmq-3.2.6.tar.gz

tar -zxvf alibaba-rocketmq-3.2.6.tar.gz

mv alibaba-rocketmq-3.2.6 rocketmq

  • 1
  • 2
  • 3
  • 4

cd rocketmq/bin 进入rocketmq核心命令文件目录

2.设置可执行权限

chmod +x mqadmin mqbroker mqfiltersrv mqshutdown  mqnamesrv

  • 1

3.修改jvm参数

vim修改runserver.shrunbroker.shjvm参数如下(根据虚拟机内存大小设置,超出内存大小可能会报错):

JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=320m"

  • 1
  • 2

4.启动nameserver

nohup sh mqnamesrv &

  • 1

5.配置broker

(1)创建broker配置文件

mkdir ../conf/me-2m-2s-async/

sh mqbroker -m >../conf/me-2m-2s-async/broker.p

  • 1
  • 2

(2)修改brokerIP

vi ../conf/me-2m-2s-async/broker.p

brokerIP1=192.168.x.x  显示指定为虚拟机的外网IP,不要用localhost127.0.0.1,因为远程主机会根据brokerIP1指定的地址去访问broker

  • 1
  • 2

6.启动broker

nohup sh mqbroker -n localhost:9876 -c ../conf/me-2m-2s-async/broker.p &

  • 1

7.检查nameserverbroker是否启动成功

执行jps,输出以下进程表示启动成功

8464 NamesrvStartup

8618 BrokerStartup

  • 1
  • 2

或者,查看nuhup.out日志文件,有如下信息表示启动成功

The Name Server boot success.

The broker[localhost.localdomain, 192.168.x.x:10911] boot success. and name server is localhost:9876

  • 1
  • 2

或者,启动rocketmq自带的ProducerConsumer程序,若可正常发送和消费消息,则表示服务启动成功

bash tools.sh com.alibaba.rocketmq.example.quickstart.Producer #生产者

bash tools.sh com.alibaba.rocketmq.example.quickstart.Consumer #消费者

  • 1
  • 2

8.关闭nameserverbroker的方法

sh mqshutdown broker

sh mqshutdown namesrv

  • 1
  • 2

安装、启动rocketmq-console

wget https://github.com/duomu/rocketmq-console/raw/master/rocketmq-console.war 下载

rocketmq-console.war放在/usr/tomcat/webapps目录下

sh /usr/tomcat/bin/startup.sh  启动tomcat

  • 1
  • 2
  • 3

虚拟机本地访问http://localhost:8080/rocketmq-console,显示如下页面表示启动成功 

宿主机远程访问http://192.168.x.x:8080/rocketmq-console,若无法访问,请检查防火墙是否关闭或者是否开放了8080端口号。

编写测试程序

在宿主机(windows)上编写如下测试程序:

依赖配置

//此处只列出mq相关的依赖

<dependency>

    <groupId>com.alibaba.rocketmq</groupId>

    <artifactId>rocketmq-client</artifactId>

    <version>3.2.6</version>

</dependency>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

创建生产者

package com.fuscent.infoquery.practice.rocketmq;

 

import com.alibaba.rocketmq.client.producer.DefaultMQProducer;

import com.alibaba.rocketmq.client.producer.SendResult;

import com.alibaba.rocketmq.common.message.Message;

import org.apache.log4j.Logger;

 

/**

 * @authorduomu

 * @date2017/8/4 18:09

 */

public class MqProducer {

    private static Logger logger = Logger.getLogger(MqProducer.class);

    public static void main(String[] args) {

        DefaultMQProducer producer = new DefaultMQProducer("Producer");

        producer.setNamesrvAddr("192.168.229.132:9876");

        try {

            producer.start();

            logger.info("producer启动成功");

            for (int i = 0; i < 5; i++) {

                Message msg = new Message("TopicA", "tagA", "OrderID188", "Hello world".getBytes());

                SendResult result = producer.send(msg);

                logger.info("id" + result.getMsgId() + " result:" + result.getSendStatus());

            }

        } catch (Exception e) {

            logger.error("发送消息失败,Exception error" + e);

        } finally {

            producer.shutdown();

        }

    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

创建消费者

package com.fuscent.infoquery.practice.rocketmq;

 

import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;

import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;

import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;

import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;

import com.alibaba.rocketmq.client.exception.MQClientException;

import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;

import com.alibaba.rocketmq.common.message.Message;

import com.alibaba.rocketmq.common.message.MessageExt;

import org.apache.log4j.Logger;

import java.util.List;

 

/**

 * @authorduomu

 * @date2017/8/4 18:09

 */

public class MqConsumer {

    private static Logger logger = Logger.getLogger(MqConsumer.class);

 

    public static void main(String[] args) {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("PushConsumer_yll");

        consumer.setNamesrvAddr("192.168.229.132:9876");

        try {

            consumer.subscribe("TopicA", "tagA||tagB");//可订阅多个tag,但是一个消息只能有一个tag

            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

            consumer.registerMessageListener(new MessageListenerConcurrently() {

                @Override

                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {

                    Message msg = list.get(0);

                    logger.info(msg.toString());

                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

                }

            });

            consumer.start();

            logger.info("consumer启动成功");

        } catch (MQClientException e) {

            logger.error("消费者订阅消息失败,error" + e);

        }

    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

测试生成者和消费者

启动生成者

启动消费者

总结

前人栽树,后人乘凉,在baidu+googlen篇文章后,终于把rocketmq搭建成功了,虽然只是单机配置,但是把该踩的坑都踩了,集群搭建应该只是多配几台服务而已,后续再研究啦~~~

1

github上下载了最新的rocketmq4.1.0,后来发现maven中央仓库还没有4.1.0rocketmq-client依赖包,后来下载了3.5.8,也没有调成功,索性下载一个比较早期的版本,选了3.2.6,我们公司用的3.2.4,比我们公司的早一点点应该不会太差。。。

2

nameserverbroker启动成功,宿主机上的生产者发送消息失败,报如下错误,且指向错误码33/44/50

com.alibaba.rocketmq.client.exception.MQClientException:Send [1] times, still failed, cost [75]ms,...

  • 1

出现这个问题首先要查看虚拟机本地的producer是否可以正常发送消息,如果本地收发消息正常,那么一定远程访问的过程中出了问题,可能是端口号没开放,也可能是IP地址映射有问题。

对于端口号,我已经确定了n遍,防火墙是关闭的,最初还没有考虑到IP地址的问题,所以百思不得其解,从阿里官方渠道获取了错误33/44/50的解决方案,试了一下也没用,把rocketmq3.2.6源码里面的Producer跑了一下也是报那个错误,错误44的说明里写着可能是producer没有正确连接到NameServer,我知道没有连接成功,可是防火墙我都关闭了还能有什么原因呢。

捣鼓了大半天,就卡在这个问题上了,我想我一定是漏掉了什么,反反复复看38/44/50的错误说明,直到看到错误50说明里面的这一句话:

然后我注意到下面这个嵌套错误,debug了一下,也没看出什么,当时我还以为这个ip是虚拟机的局域网ip

接着就baidu+google,偶然google出一篇思路别具一格的文章,说rocketmq自动识别网络出错,要把其他网络关掉,我之前学习docker的时候的确在虚拟机上配了docker的网络。

然后就尝试关掉docker的网络(172.17.0.1),可是关掉了还是照样报上面的错误啊。。。

真的没有办法了,今天早晨来了突然想到,能够访问外网ip不能访问局域网ipping一下看看吧,果然局域网ip ping不通,由于对网络、虚拟机了解的不深,我就去求教网络童鞋了,问宿主机怎么能够访问虚拟机的局域网ip(我用的NAT模式),网络童鞋说你用桥接模式吧,当时心中暗喜,心想吼吼我的大难题就要这么简单的解决了,网络童鞋走后,我就试了一下,麻蛋为什么用桥接模式分了新的ip172.16.2.129),还是报上面那个172.17.0.1的错误。。

第一次搭rocketmq,想尽快调通,基本上都是用的默认配置,而且默认配置一般不会有问题啊,自己写配置才容易出错,然鹅万能的百度告诉我我之前先入为主的观念是错的,我想这应该是终极解决方案了吧。。

原来broker自动寻的地址是172.17.0.1,而且深深的刻在了默认配置文件里,虽然我关掉了这个网络,配置文件里还是这个地址,然后我重新写了个配置文件,强制指定broker所在的机器ip192.168.x.x,重启服务,大功告成!

和局域网ip能否ping通无关,我把网络连接改回了NAT模式,感谢网络童鞋的帮忙,我要好好补一下网络和虚拟机的知识了。。。

参考资料

附上最有价值的几个~~ 
http://rocketmq.apache.org/docs/quick-start/ 
官方资料,搭建mq之前最好把User Guide都看一遍 
https://firsh.me/2017/07/19/rocketmq-p-c/ 
https://my.oschina.net/xcafe/blog/814135 
2的终极解决方案 
http://www.cnblogs.com/badboyf/p/6611774.html

 

 

 

  •  

窗体顶端

 

窗体底端

×

广告

RocketMQ 实战之快速入门

 

冯先生的笔记 关注

2017.06.06 21:58* 字数 2431 阅读 111011评论 26喜欢 110赞赏 4

最近 RocketMQ 刚刚上生产环境,闲暇之时在这里做一些分享,主要目的是让初学者能快速上手RocketMQ

RocketMQ 是什么

Github 上关于 RocketMQ 的介绍:
RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件。具有以下特性:

  1. 支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型
  2. 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递
  3. 支持拉(pull)和推(push)两种消息模式
  4. 单一队列百万消息的堆积能力
  5. 支持多种消息协议,如 JMSMQTT
  6. 分布式高可用的部署架构,满足至少一次消息传递语义
  7. 提供 docker 镜像用于隔离测试和云集群部署
  8. 提供配置、指标和监控等功能丰富的 Dashboard

对于这些特性描述,大家简单过一眼就即可,深入学习之后自然就明白了。

专业术语

Producer

消息生产者,生产者的作用就是将消息发送到 MQ,生产者本身既可以产生消息,如读取文本信息等。也可以对外提供接口,由外部应用来调用接口,再由生产者将收到的消息发送到 MQ

Producer Group

生产者组,简单来说就是多个发送同一类消息的生产者称之为一个生产者组。在这里可以不用关心,只要知道有这么一个概念即可。

Consumer

消息消费者,简单来说,消费 MQ 上的消息的应用程序就是消费者,至于消息是否进行逻辑处理,还是直接存储到数据库等取决于业务需要。

Consumer Group

消费者组,和生产者类似,消费同一类消息的多个 consumer 实例组成一个消费者组。

Topic

Topic 是一种消息的逻辑分类,比如说你有订单类的消息,也有库存类的消息,那么就需要进行分类,一个是订单 Topic 存放订单相关的消息,一个是库存 Topic 存储库存相关的消息。

Message

Message 是消息的载体。一个 Message 必须指定 topic,相当于寄信的地址。Message 还有一个可选的 tag 设置,以便消费端可以基于 tag 进行过滤消息。也可以添加额外的键值对,例如你需要一个业务 key 来查找 broker 上的消息,方便在开发过程中诊断问题。

Tag

标签可以被认为是对 Topic 进一步细化。一般在相同业务模块中通过引入标签来标记不同用途的消息。

Broker

Broker RocketMQ 系统的主要角色,其实就是前面一直说的 MQBroker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。

Name Server

Name Server producer consumer 提供路由信息。

RocketMQ 架构

RocketMQ 架构

由这张图可以看到有四个集群,分别是 NameServer 集群、Broker 集群、Producer 集群和 Consumer 集群:

  1. NameServer: 提供轻量级的服务发现和路由。 每个 NameServer 记录完整的路由信息,提供等效的读写服务,并支持快速存储扩展。
  2. Broker: 通过提供轻量级的 Topic Queue 机制来处理消息存储,同时支持推(push)和拉(pull)模式以及主从结构的容错机制。
  3. Producer:生产者,产生消息的实例,拥有相同 Producer Group Producer 组成一个集群。
  4. Consumer:消费者,接收消息进行消费的实例,拥有相同 Consumer Group
    Consumer 组成一个集群。

简单说明一下图中箭头含义,从 Broker 开始,Broker Master1 Broker Slave1 是主从结构,它们之间会进行数据同步,即 Date Sync。同时每个 Broker
NameServer 集群中的所有节
点建立长连接,定时注册 Topic 信息到所有 NameServer 中。

Producer NameServer 集群中的其中一个节点(随机选择)建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Broker Master 建立长连接,且定时向 Broker 发送心跳。Producer 只能将消息发送到 Broker master,但是 Consumer 则不一样,它同时和提供 Topic 服务的 Master Slave
建立长连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。

RocketMQ 集群部署模式

  1. master 模式
    也就是只有一个 master 节点,称不上是集群,一旦这个 master 节点宕机,那么整个服务就不可用,适合个人学习使用。
  2. master 模式
    多个 master 节点组成集群,单个 master 节点宕机或者重启对应用没有影响。
    优点:所有模式中性能最高
    缺点:单个 master 节点宕机期间,未被消费的消息在节点恢复之前不可用,消息的实时性就受到影响。
    注意:使用同步刷盘可以保证消息不丢失,同时 Topic 相对应的 queue 应该分布在集群中各个节点,而不是只在某各节点上,否则,该节点宕机会对订阅该 topic 的应用造成影响。
  3. master slave 异步复制模式
    在多 master 模式的基础上,每个 master 节点都有至少一个对应的 slavemaster
    节点可读可写,但是 slave 只能读不能写,类似于 mysql 的主备模式。
    优点: master 宕机时,消费者可以从 slave 读取消息,消息的实时性不会受影响,性能几乎和多 master 一样。
    缺点:使用异步复制的同步方式有可能会有消息丢失的问题。
  4. master slave 同步双写模式
    同多 master slave 异步复制模式类似,区别在于 master slave 之间的数据同步方式。
    优点:同步双写的同步模式能保证数据不丢失。
    缺点:发送单个消息 RT 会略长,性能相比异步复制低10%左右。
    刷盘策略:同步刷盘和异步刷盘(指的是节点自身数据是同步还是异步存储)
    同步方式:同步双写和异步复制(指的一组 master slave 之间数据的同步)
    注意:要保证数据可靠,需采用同步刷盘和同步双写的方式,但性能会较其他方式低。

RocketMQ 单主部署

鉴于是快速入门,我选择的是第一种单 master 的部署模式。先说明一下我的安装环境:

  1. Centos 7.2
  2. jdk 1.8
  3. Maven 3.2.x
  4. Git

这里 git 可用可不用,主要是用来直接下载 github 上的源码。也可以选择自己到
github 上下载,然后上传到服务器上。以git操作为示例。

  1. clone 源码并用 maven 编译

> git clone https://github.com/alibaba/RocketMQ.git /opt/RocketMQ

> cd /opt/RocketMQ && mvn -Dmaven.test.skip=true clean package install assembly:assembly -U

> cd target/alibaba-rocketmq-broker/alibaba-rocketmq

此处可能遇到的问题
一、执行"git clone https://github.com/alibaba/RocketMQ.git/home/inspkgs/RocketMQ"时出现以下提示:

fatal: unable to access 'https://github.com/alibaba/RocketMQ.git/': Could not resolve host: github.com; Unknown error

解决办法:一般是由于网络原因造成的,执行以下命令

> ping github.com

确定可以 ping 通之后,再重新执行 git clone 命令。
二、执行"mvn -Dmaven.test.skip=true clean package install assembly:assembly -U"编译时,可能出现下载相关jar很慢的情况。
这也是由于默认 maven 中央仓库在国外的原因,可以根据需要在 /home/maven/conf/setting.xml 中的 <mirrors></mirrors> 添加以下内容后重新编译:

<mirror>

    <id>aliyun</id>

    <mirrorOf>central</mirrorOf>

    <name>aliyun maven</name>

    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>

</mirror>

  1. 启动 Name Server

> nohup sh /opt/RocketMQ/bin/mqnamesrv &

//执行 jps 查看进程

> jps

25913 NamesrvStartup

//查看日志确保服务已正常启动

> tail -f ~/logs/rocketmqlogs/namesrv.log

The Name Server boot success...

  1. 启动 broker

> nohup sh /opt/RocketMQ/bin/mqbroker -n localhost:9876 &

//执行 jps 查看进程

> jps

25954 BrokerStartup

//查看日志确保服务已正常启动

> tail -f ~/logs/rocketmqlogs/broker.log

The broker[broker-a, 10.1.54.121:10911] boot success...

  1. 发送和接收消息
    发送/接收消息之前,我们需要告诉客户端 NameServer 地址。RocketMQ 提供了多种方式来实现这一目标。为简单起见,我们使用环境变量 NAMESRV_ADDR

> export NAMESRV_ADDR=localhost:9876

> sh /opt/RocketMQ/bin/tools.sh com.alibaba.rocketmq.example.quickstart.Producer

SendResult [sendStatus=SEND_OK, msgId= ...

> sh /opt/RocketMQ/bin/tools.sh com.alibaba.rocketmq.example.quickstart.Consumer

ConsumeMessageThread_%d Receive New Messages: [MessageExt...

  1. 关闭服务

> sh /opt/RocketMQ/bin/mqshutdown broker

The mqbroker(36695) is running...

Send shutdown request to mqbroker(36695) OK

> sh /opt/RocketMQ/bin/mqshutdown namesrv

The mqnamesrv(36664) is running...

Send shutdown request to mqnamesrv(36664) OK

生产者、消费者 Demo

  1. 生产者

public class Producer {

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

 

        //声明并初始化一个producer

        //需要一个producer group名字作为构造方法的参数,这里为producer1

        DefaultMQProducer producer = new DefaultMQProducer("producer1");

       

        //设置NameServer地址,此处应改为实际NameServer地址,多个地址之间用;分隔

        //NameServer的地址必须有,但是也可以通过环境变量的方式设置,不一定非得写死在代码里

        producer.setNamesrvAddr("10.1.54.121:9876;10.1.54.122:9876");

       

        //调用start()方法启动一个producer实例

        producer.start();

 

        //发送10条消息到TopicTopicTesttagTagA,消息内容为“Hello RocketMQ”拼接上i的值

        for (int i = 0; i < 10; i++) {

            try {

                Message msg = new Message("TopicTest",// topic

                        "TagA",// tag

                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)// body

                );

               

                //调用producersend()方法发送消息

                //这里调用的是同步的方式,所以会有返回结果

                SendResult sendResult = producer.send(msg);

               

                //打印返回结果,可以看到消息发送的状态以及一些相关信息

                System.out.println(sendResult);

            } catch (Exception e) {

                e.printStackTrace();

                Thread.sleep(1000);

            }

        }

 

        //发送完消息之后,调用shutdown()方法关闭producer

        producer.shutdown();

    }

}

  1. 消费者

public class Consumer {

 

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

   

        //声明并初始化一个consumer

        //需要一个consumer group名字作为构造方法的参数,这里为consumer1

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer1");

 

        //同样也要设置NameServer地址

        consumer.setNamesrvAddr("10.1.54.121:9876;10.1.54.122:9876");

 

        //这里设置的是一个consumer的消费策略

        //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,即跳过历史消息

        //CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍

        //CONSUME_FROM_TIMESTAMP 从某个时间点开始消费,和setConsumeTimestamp()配合使用,默认是半个小时以前

        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

 

        //设置consumer所订阅的TopicTag*代表全部的Tag

        consumer.subscribe("TopicTest", "*");

 

        //设置一个Listener,主要进行消息的逻辑处理

        consumer.registerMessageListener(new MessageListenerConcurrently() {

 

            @Override

            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,

                                                            ConsumeConcurrentlyContext context) {

 

                System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs);

               

                //返回消费状态

                //CONSUME_SUCCESS 消费成功

                //RECONSUME_LATER 消费失败,需要稍后重新消费

                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

            }

        });

 

        //调用start()方法启动consumer

        consumer.start();

 

        System.out.println("Consumer Started.");

    }

}

本篇到此完结,第一次写文章,表达不清楚的地方还请各位小伙伴海涵。如有问题,可以多多交流。如果后面有时间的话,我也会分享更多的干货,包括
producerconsumer API 详解、如何与 spring boot 整合、生产环境部署的一些注意事项,以及学习 RocketMQ 这一路踩过的坑等等。

最后,如果觉得写的还过得去,点个喜欢或者小小打赏一下都是一种肯定,谢谢大家的支持。

ps:偶然的机会看到自己写的文章出现在一个个人网站,当我通过QQ联系那个人询问这件事时,还被直接拉黑,真的很郁闷。在此,我想说,想要用我的作品可以,但一定要征得我同意,这是对一个作者最基本的尊重。

  •  

https://www.jianshu.com/p/824066d70da8

发布了48 篇原创文章 · 获赞 4 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39879632/article/details/83870650