Spring Cloud Alibaba RocketMQ - 構建異步通信的微服務

MQ的選擇

消息隊列對比參照表:


image.png

RocketMQ vs. ActiveMQ vs. Kafka:


image.png

參考至:


CentOS7上搭建RocketMQ

環境要求:

  • CentOS 7.2
  • 64位JDK1.8+
  • 4G+的可用磁盤空間

1、下載RocketMQ的二進制包,我這里使用的是4.5.1版本,下載地址如下:

http://rocketmq.apache.org/release_notes/release-notes-4.5.1/

使用wget命令下載:

[root@study-01 ~]# cd /usr/local/src
[root@study-01 /usr/local/src]# wget http://mirror.bit.edu.cn/apache/rocketmq/4.5.1/rocketmq-all-4.5.1-bin-release.zip

2、解壓下載好的壓縮包,并移動到合適的目錄下:

[root@study-01 /usr/local/src]# unzip rocketmq-all-4.5.1-bin-release.zip
[root@study-01 /usr/local/src]# mv rocketmq-all-4.5.1-bin-release /usr/local/rocketmq-4.5.1

注:若沒有安裝unzip命令則使用如下命令安裝:
yum install -y unzip

3、進入rocketmq的根目錄并查看是否包含如下目錄及文件:

[root@study-01 /usr/local/src]# cd /usr/local/rocketmq-4.5.1
[root@study-01 /usr/local/rocketmq-4.5.1]# ls
benchmark  bin  conf  lib  LICENSE  NOTICE  README.md

4、沒問題后,使用如下命令啟動Name Server:

[root@study-01 /usr/local/rocketmq-4.5.1]# nohup sh bin/mqnamesrv &
[1] 2448
[root@study-01 /usr/local/rocketmq-4.5.1]# 

5、查看默認的9876端口是否被監聽,以驗證Name Server是否啟動成功:

[root@study-01 /usr/local/rocketmq-4.5.1]# netstat -lntp |grep java
tcp6       0      0 :::9876                 :::*                    LISTEN      2454/java           
[root@study-01 /usr/local/rocketmq-4.5.1]#

6、啟動Broker:

[root@study-01 /usr/local/rocketmq-4.5.1]# nohup sh bin/mqbroker -n localhost:9876 &
[2] 2485
[root@study-01 /usr/local/rocketmq-4.5.1]# 

7、驗證Broker是否啟動成功,如果啟動成功,能看到類似如下的日志::

[root@study-01 /usr/local/rocketmq-4.5.1]# cat ~/logs/rocketmqlogs/broker.log |grep "boot success"
2019-08-04 01:27:38 INFO main - The broker[study-01, 192.168.190.129:10911] boot success. serializeType=JSON and name server is localhost:9876
[root@study-01 /usr/local/rocketmq-4.5.1]# 

若想停止Name Server和Broker,則依次執行以下兩條命令即可:

[root@study-01 /usr/local/rocketmq-4.5.1]# sh bin/mqshutdown broker
The mqbroker(2492) is running...
Send shutdown request to mqbroker(2492) OK  # 輸出該信息說明停止成功
[root@study-01 /usr/local/rocketmq-4.5.1]# sh bin/mqshutdown namesrv
The mqnamesrv(2454) is running...
Send shutdown request to mqnamesrv(2454) OK  # 輸出該信息說明停止成功
[2]+  退出 143              nohup sh bin/mqbroker -n localhost:9876
[root@study-01 /usr/local/rocketmq-4.5.1]#

驗證RocketMQ功能是否正常

1、驗證生產消息正常,執行如下命令:

[root@study-01 /usr/local/rocketmq-4.5.1]# export NAMESRV_ADDR=localhost:9876
[root@study-01 /usr/local/rocketmq-4.5.1]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

正常的情況下,會看到一堆的類似于如下的輸出,這是生產消息后成功的result:

SendResult [sendStatus=SEND_OK, msgId=C0A8BE810A690D7163610FCC253B03E7, offsetMsgId=C0A8BE8100002A9F000000000002BDFE, messageQueue=MessageQueue [topic=TopicTest, brokerName=study-01, queueId=3], queueOffset=249]

2、驗證消費消息正常,執行如下命令:

[root@study-01 /usr/local/rocketmq-4.5.1]# sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

正常的情況下,會看到一堆的類似于如下的輸出,這是消費的消息內容:

ConsumeMessageThread_6 Receive New Messages: [MessageExt [queueId=3, storeSize=180, queueOffset=242, sysFlag=0, bornTimestamp=1564853837073, bornHost=/192.168.190.129:34708, storeTimestamp=1564853837074, storeHost=/192.168.190.129:10911, msgId=C0A8BE8100002A9F000000000002AA4E, commitLogOffset=174670, bodyCRC=911284903, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=250, CONSUME_START_TIME=1564854006859, UNIQ_KEY=C0A8BE810A690D7163610FCC251103CB, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 57, 55, 49], transactionId='null'}]]

搭建RocketMQ控制臺

RocketMQ官方提供了一個基于Spring Boot開發的可視化控制臺,可以方便我們查看RocketMQ的運行情況以及提升運維效率。所以本小節將介紹一下如何搭建搭建RocketMQ的控制臺,由于我們使用的RocketMQ版本是4.5.1,所以需要對控制臺的源碼進行一些改動以適配RocketMQ的4.5.1版本。

1、首先需要下載源碼,有兩種方式,一是使用git克隆代碼倉庫,二是直接下載rocketmq-externals的zip包,我這里使用git方式,執行如下命令:

git clone https://github.com/apache/rocketmq-externals.git

2、修改控制臺代碼,使用IDE打開rocketmq-console項目,如下圖所示:

image.png

2.1、修改項目中的application.properties配置文件,我這里主要是修改了監聽端口和Name Server的連接地址,至于其他配置項有需要的話可按照說明自行修改:

# console的監聽端口,默認是8080
server.port=8011
# Name Server的連接地址;非必須,可以在啟動了console后,在控制臺導航欄 - 運維 - NameSvrAddrList一欄設置
rocketmq.config.namesrvAddr=192.168.190.129:9876

2.2、修改依賴,由于console項目默認使用的rocketmq版本是4.4.0,與我們這里使用的是4.5.1不完全兼容,所以需要修改一下依賴版本,找到這一行:

<rocketmq.version>4.4.0</rocketmq.version>

修改為:

<rocketmq.version>4.5.1</rocketmq.version>

2.3、修改代碼,由于修改了rocketmq的版本,會導致org.apache.rocketmq.console.service.impl.MessageServiceImpl#queryMessageByTopic方法編譯報錯,所以需要改動一下此處代碼 ,將:

@Override
public List<MessageView> queryMessageByTopic(String topic, final long begin, final long end) {
    DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP, null);
    ...

修改為:

@Override
public List<MessageView> queryMessageByTopic(String topic, final long begin, final long end) {
    RPCHook rpcHook = null;
    DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP, rpcHook);
    ...

3、打包構建并啟動,打開idea的terminal,執行如下命令:

# 在rocketmq-console目錄下執行
mvn clean package -DskipTests

# 進入jar包存放目錄
cd target

# 啟動rocketmq console
java -jar rocketmq-console-ng-1.0.1.jar

4、使用瀏覽器訪問控制臺,我這里由于修改了端口,所以訪問地址是:http://localhost:8011,正常的情況下能看到如下界面:

image.png

不習慣英文的話可以在右上角切換語言:


image.png

由于控制臺是可視化界面并且支持中文,這里就不過多介紹了,可以參考官方的控制臺使用說明文檔:


RocketMQ術語與概念

我這里將基本的術語與概念簡單總結成了思維導圖:


官方文檔:


Spring消息編程模型 - 編寫生產者

在以上小節搭建完RocketMQ之后,我們來使用Spring的消息編程模型,編寫一個簡單的示例。首先需要在項目中添加相關依賴如下:

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

在配置文件中添加rocketmq相關的配置如下:

rocketmq:
  name-server: 192.168.190.129:9876
  producer:
    # 小坑:必須指定group
    group: test-group

編寫生產者的代碼,這里以Controller做示例,具體代碼如下:

package com.zj.node.contentcenter.controller.content;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 生產者
 *
 * @author 01
 * @date 2019-08-03
 **/
@RestController
@RequiredArgsConstructor
public class TestProducerController {

    /**
     * 用于發送消息到 RocketMQ 的api
     */
    private final RocketMQTemplate rocketMQTemplate;

    @GetMapping("/test-rocketmq/sendMsg")
    public String testSendMsg() {
        String topic = "test-topic";
        // 發送消息
        rocketMQTemplate.convertAndSend(topic, Message.getInstance());

        return "send message success";
    }
}

@Data
class Message {
    private Integer id;
    private String name;
    private String status;
    private Date createTime;

    static Message getInstance() {
        Message message = new Message();
        message.id = 1;
        message.name = "小明";
        message.status = "default";
        message.createTime = new Date();

        return message;
    }
}

編寫完成后,啟動項目,訪問該接口:


image.png

消息發送成功后,可以到RocketMQ的控制臺中進行查看:


image.png

消息體可以在消息詳情中查看,如下:


image.png

從生產者的代碼來看,可以說是十分的簡單了,只需要使用一個RocketMQTemplate就可以實現將對象轉換成消息體并發送消息。實際上除了RocketMQ外,其他的MQ也有對應的Template,如下:

  • RocketMQ:RocketMQTemplate
  • ActiveMQ/Artemis:JmsTemplate
  • RabbitMQ:AmqpTemplate
  • Kafka:KafkaTemplate

Spring消息編程模型 - 編寫消費者

在消費者項目中,也需要添加rocketmq的依賴:

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

同樣需要配置Name Server的連接地址:

rocketmq:
  name-server: 192.168.190.129:9876

編寫消費者的代碼,具體代碼如下:

package com.zj.node.usercenter.rocketmq;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 消費者監聽器
 *
 * @author 01
 * @date 2019-08-03
 **/
@Slf4j
@Component
// topic需要和生產者的topic一致,consumerGroup屬性是必須指定的,內容可以隨意
@RocketMQMessageListener(topic = "test-topic", consumerGroup = "consumer-group")
public class TestConsumerListener implements RocketMQListener<Message> {

    /**
     * 監聽到消息的時候就會調用該方法
     *
     * @param message 消息體
     */
    @Override
    public void onMessage(Message message) {
        log.info("從test-topic中監聽到消息");
        log.info(JSON.toJSONString(message));
    }
}

/**
 * 消息體結構需要一致
 */
@Data
class Message {
    private Integer id;
    private String name;
    private String status;
    private Date createTime;
}

編寫完成后啟動項目,由于之前我們已經往隊列里發送了消息,所以此時消費者項目一啟動,就可以監聽到消息并消費,控制臺就會輸出如下日志:


image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容