Rocketmq安装以及初探

191 阅读7分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

目前java开发中经常会使用到消息中间件也就是消息队列。目前用的比较多的就是Rabbit MQ和Rocket MQ了。最近在帮甲方做一个项目,正好有个功能需要用到消息队列来解决,由于甲方公司之前的其它项目中有使用到Rocket MQ,我从技术栈统一的角度考虑,在技术选型上也考虑使用Rocket MQ来作为这次项目中的消息中间件。

首先我们需要在服务器上安装我们的Rocket MQ中间件,

打开官网的下载页面(Quick Start - Apache RocketMQ)或者跳转到GitHub上下载自己想要的版本。我这边为了和之前项目保持版本一致选择了4.6.0版本。

将安装压缩包上传到服务器,然后进行解压缩。进入rocketmq-4.6.0,可以看到如下的目录

drwxr-xr-x 2 root root 83 Mar 4 10:51 benchmark

drwxr-xr-x 3 root root 4096 Mar 31 18:30 bin

drwxr-xr-x 6 root root 211 Mar 31 18:29 conf

drwxr-xr-x 2 root root 4096 Mar 4 10:51 lib

-rw-r--r-- 1 root root 17336 Mar 4 10:51 LICENSE

-rw------- 1 root root 41 Mar 4 10:53 nohup.out

-rw-r--r-- 1 root root 1338 Mar 4 10:51 NOTICE

-rw-r--r-- 1 root root 4225 Mar 4 10:51 README.md

bin目录主要是执行启动命令的,conf存放我们的配置文件。我在使用过程中主要使用了这两个目录。因为实在测试环境中,为了节省内存资源,我这边会修改rocketmq的启动时的jvm参数,所以在bin目录下,找到runserver.sh文件。通过vim命令打开

JAVA_OPT="${JAVA_OPT} -server -Xms128m -Xmx128m -Xmn64m -XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=64m"

JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled

-XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC"

JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails"

JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"

JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"

JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"

JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"

#JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n"

JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"

JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"

看到第一行,这里实我调整后的jvm参数,可以根据自己服务器的资源来适当降低或升高内存的分配。

另一个就是修改bin目录下的runbroker.sh文件。找到下面这段配置

JAVA_OPT="${JAVA_OPT} -server -Xms128m -Xmx128m -Xmn64m"

JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerM

B=0"

JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationSt

oppedTime -XX:+PrintAdaptiveSizePolicy"

JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"

JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"

JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"

JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"

JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"

JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"

#JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n"

JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"

JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"

和前面一样,自定义修改jvm的参数。因为如果你的服务器配置不高的话,默认rocketmq分配的内存时很大的,是4g。假设你的服务器内存资源不够那么就会无法启动。

然后我们需要修改conf/broker.conf文件。这里主要是配置服务的地址,在文件末尾添加下面的配置

brokerIP1=127.0.0.1

namesrvAddr=127.0.0.1:9876

autoCreateTopicEnable=true

可以把127.0.0.1替换成自己的服务IP,这里主要是为了配置对外的网络地址,最后一个是为了开启消息队列自动创建主题的功能,默认这个功能是关闭的,开启后,如果我们的消费者监听了某个主题,而队列中又没有这个主题的话,就会直接创建一个主题。

到此我们的配置就已经结束了,可以启动mq来试试。按照官方文档,我们切换到bin目录下需要先执行

nohup sh mqnamesrv & 
在你当前用户的目录下有个logs目录,里面会生成一个rocketmqlogs文件夹,rocketmq的运行日志就存放在这里,我们打开里面的namesrv.log日志文件
2021-12-10 11:17:49 INFO main - The Name Server boot success. serializeType=JSON

出现上面的日志就算namesrv成功启动,然后按照文档我们需要启动broker,同样在bin目录下执行下面的命令

nohup sh runbroker.sh -n 127.0.0.1:9876 -c ../conf/broker.conf

这里是指启动命令时配置namesrv的地址,同时加载broker.conf的配置。然后我们在之前查看namesrv目录

2022-03-04 15:51:26 INFO main - The broker[broker-a, 127.0.0.1:10911] boot success. serializeType=JSON and name server is 127.0.0.1:9876

看到上面success的输出就说明broker启动成功了。OK,既然我们的rocketmq已经搭建成功那么我们就应该使用我们的代码来尝试下。

首先我们新建一个工程,在maven中加入依赖

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.1</version>
</dependency>

我们按照官网提供的小案例来测试下rocketmq的同步消息。

首先我们编写一个消息生产者

public static void main(String[] args) throws Exception {
    //实例化一个生产者
    DefaultMQProducer producer = new
            DefaultMQProducer("self_producer");
    //声明mq的地址
    producer.setNamesrvAddr("127.0.0.1:9876");
    DefaultChannelId.newInstance();
    //启动实例
    producer.start();
    for (int i = 0; i < 3; i++) {
        //创建一个消息实体,声明了投递的主题,标签,和消息内容
        Message msg = new Message("TopicTest" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " +
                        i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
        );
        //同步消息,获取消息投递到broker的结果
        SendResult sendResult = producer.send(msg);
        System.out.printf("%s%n", sendResult);
    }
    //Shut down once the producer instance is not longer in use.
    //producer.shutdown();避免生产者停止
}

然后是编写消费者的代码

public static void main(String[] args) throws InterruptedException, MQClientException {
    //创建一个消费者
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("self_consumer");
    // 声明rocketmq的地址
    consumer.setNamesrvAddr("127.0.0.1:9876");
    //订阅一个主题,同时进行标签的过滤,*表示接受所有的标签
    consumer.subscribe("TopicTest", "*");
    // 注册一个监听器来监听来自broker的消息
    consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
        //返回应答
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    });
    DefaultChannelId.newInstance();
    //这里启动消费者
    consumer.start();
    System.out.printf("Consumer Started.%n");
}

首先我们先启动消费者,启动成功之后再启动生产者,然后分别观察两个服务的日志输出

生产者日志

14:02:16.588 [main] DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
SendResult [sendStatus=SEND_OK, msgId=7F00000131A018B4AAC212763D520000, offsetMsgId=792B291300002A9F0000000000049AE2, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=2], queueOffset=251]
SendResult [sendStatus=SEND_OK, msgId=7F00000131A018B4AAC212763D8A0001, offsetMsgId=792B291300002A9F0000000000049BAB, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=3], queueOffset=250]
SendResult [sendStatus=SEND_OK, msgId=7F00000131A018B4AAC212763DBE0002, offsetMsgId=792B291300002A9F0000000000049C74, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=0], queueOffset=251]

这样表明消息已经成功投递到我们的rocketmq中了,然后是消费者的日志

ConsumeMessageThread_1 Receive New Messages: [MessageExt [brokerName=broker-a, queueId=2, storeSize=201, queueOffset=251, sysFlag=0, bornTimestamp=1649052138837, bornHost=/122.231.128.38:42623, storeTimestamp=1649052137734, storeHost=/127.0.0.1:10911, msgId=792B291300002A9F0000000000049AE2, commitLogOffset=301794, bodyCRC=613185359, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=252, CONSUME_START_TIME=1649052138898, UNIQ_KEY=7F00000131A018B4AAC212763D520000, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 48], transactionId='null'}]] 
ConsumeMessageThread_2 Receive New Messages: [MessageExt [brokerName=broker-a, queueId=3, storeSize=201, queueOffset=250, sysFlag=0, bornTimestamp=1649052138890, bornHost=/122.231.128.38:42623, storeTimestamp=1649052137779, storeHost=/127.0.0.1:10911, msgId=792B291300002A9F0000000000049BAB, commitLogOffset=301995, bodyCRC=1401636825, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=251, CONSUME_START_TIME=1649052138943, UNIQ_KEY=7F00000131A018B4AAC212763D8A0001, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 49], transactionId='null'}]] 
ConsumeMessageThread_3 Receive New Messages: [MessageExt [brokerName=broker-a, queueId=0, storeSize=201, queueOffset=251, sysFlag=0, bornTimestamp=1649052138942, bornHost=/122.231.128.38:42623, storeTimestamp=1649052137826, storeHost=/127.0.0.1:10911, msgId=792B291300002A9F0000000000049C74, commitLogOffset=302196, bodyCRC=1250039395, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=252, CONSUME_START_TIME=1649052138982, UNIQ_KEY=7F00000131A018B4AAC212763DBE0002, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 50], transactionId='null'}]] 

可以看到已经成功接受到了消息,说明我们的rocketmq安装成功并且可用。后面就可以使用rocketmq 来实现我们的各种功能了。