Java開發--47--Springboot整合RocketMQ訊息佇列

隨 亦發表於2020-11-29

一、RocketMQ訊息佇列介紹

簡介:RocketMQ是阿里開源的一款高效能、高吞吐量的分散式訊息中介軟體

特點:

1、在高壓下1毫秒內響應延遲超過99.6%
2、適合金融類業務,高可用性跟蹤和審計功能
3、支援釋出訂閱模型,和點對點
4、支援拉pull和推push兩種訊息模式
5、單一佇列百萬訊息
6、支援單master節點、多master節點、多master多slave節點

概念:

1、Producer:訊息生產者
2、Producer Group:訊息生產者組,傳送同類訊息的一個訊息生產組
3、Consumer:消費者
4、Consumer Group:消費同個訊息的多個例項
5、Tag:標籤,子主題,用於區分同一個主題下的不同業務的訊息
6、Topic:主題
7、Message:訊息
8、Broker:MQ程式,接收生產的訊息,提供給消費者消費的程式
9、Name Server:給生產和消費者提供路由資訊,提供輕量級的服務發現和路由

二、安裝部署

1、下載安裝包:https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip

2、解壓

3、執行

# 進入bin目錄,啟動名稱服務namesrv:
nohup sh mqnamesrv & 

# 檢視日誌
tail -f nohup.out
結尾有:The Name Server boot success. serializeType=JSON 表示啟動成功

# 啟動broker   
nohup sh mqbroker -n 127.0.0.1:9876 &

# 關閉nameserver broker
sh mqshutdown namesrv
sh mqshutdown broker

如下所示:
在這裡插入圖片描述

三、RoekerMQ視覺化控制檯

1、下載
https://github.com/apache/rocketmq-externals

2、修改配置
rocketmq-externals/rocketmq-console/src/main/resources/application.properties

# 寫這麼多是為了方便定位上下文

spring.application.name=rocketmq-console
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
logging.level.root=INFO
logging.config=classpath:logback.xml

# 主要配置這個地方,IP地址和埠號
rocketmq.config.namesrvAddr=127.0.0.1:9876

rocketmq.config.isVIPChannel=
rocketmq.config.dataPath=/tmp/rocketmq-console/data
rocketmq.config.enableDashBoardCollect=true

3、編譯打包

cd rocketmq-externals/rocketmq-console
mvn clean package -Dmaven.test.skip=true

4、target目錄下

cd target
java -jar rocketmq-console-ng-2.0.0.jar

5、訪問頁面即可

http://127.0.0.1:8080

如下所示:

在這裡插入圖片描述

四、整合RocketMQ實踐

1、​啟動nameser和broker,詳見第二節

2、加入pom.xml依賴

<properties>
	<rocketmq.version>4.7.1</rocketmq.version>
</properties>

<dependencies>
	<!-- 整合RocketMq -->
	<dependency>
		<groupId>org.apache.rocketmq</groupId>
		<artifactId>rocketmq-client</artifactId>
		<version>${rocketmq.version}</version>
	</dependency>
	
	<dependency>
		<groupId>org.apache.rocketmq</groupId>
		<artifactId>rocketmq-common</artifactId>
		<version>${rocketmq.version}</version>
	</dependency>
</dependencies>

<build>
    <finalName>hello_springboot</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!-- 新增版本號,不新增會報錯,原因未知 -->
            <version>2.3.4.RELEASE</version>
            <configuration>
            	<!--必須新增這個配置-->
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

3、配置檔案配置(application.properties)

# 消費者的組名
apache.rocketmq.consumer.PushConsumer=orderConsumer

# 生產者的組名
apache.rocketmq.producer.producerGroup=Producer

# NameServer地址
apache.rocketmq.namesrvAddr=127.0.0.1:9876

4、開發資訊生產者

jms/MsgProducer.java

@Component
// 生產者
public class MsgProducer {
    // 生產者的組名
    @Value("${apache.rocketmq.producer.producerGroup}")
    private String producerGroup;

    // NameServer 地址
    @Value("${apache.rocketmq.namesrvAddr}")
    private String namesrvAddr;

    private  DefaultMQProducer producer ;

    public DefaultMQProducer getProducer(){
        return this.producer;
    }

    @PostConstruct
    public void init() {
        // 生產者的組名
        producer = new DefaultMQProducer(producerGroup);
        // 指定NameServer地址,多個地址以 ; 隔開
        // 如 producer.setNamesrvAddr("192.168.100.141:9876;192.168.100.142:9876;");
        producer.setNamesrvAddr(namesrvAddr);

        producer.setVipChannelEnabled(false);

        try {
            // Producer物件在使用之前必須要呼叫start初始化,只能初始化一次
            producer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 一般在應用上下文,關閉的時候進行關閉,用上下文監聽器
        // producer.shutdown();
    }
}

5、開發資訊消費者

jms/MsgConsumer.java

@Component
// 消費者
public class MsgConsumer {
    // 消費者的組名
    @Value("${apache.rocketmq.consumer.PushConsumer}")
    private String consumerGroup;

    // NameServer地址
    @Value("${apache.rocketmq.namesrvAddr}")
    private String namesrvAddr;

    @PostConstruct
    public void defaultMQPushConsumer() {
        // 消費者的組名
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
        // 指定NameServer地址,多個地址以 ; 隔開
        consumer.setNamesrvAddr(namesrvAddr);

        try {
            // 設定consumer所訂閱的Topic和Tag,*代表全部的Tag
            consumer.subscribe("testTopic", "*");

            // CONSUME_FROM_LAST_OFFSET 預設策略,從該佇列最尾開始消費,跳過歷史訊息
            // CONSUME_FROM_FIRST_OFFSET 從佇列最開始開始消費,即歷史訊息(還儲存在broker的)全部消費一遍
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);


            // MessageListenerOrderly 這個是有序的
            // MessageListenerConcurrently 這個是無序的,並行的方式處理,效率高很多
            consumer.registerMessageListener((MessageListenerConcurrently) (list, context) -> {
                try {
                    for (MessageExt messageExt : list) {
                        // 輸出訊息內容
                        System.out.println("messageExt: " + messageExt);
                        String messageBody = new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET);
                        // 輸出訊息內容
                        System.out.println("消費響應:msgId : " + messageExt.getMsgId() + ",  msgBody : " + messageBody);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    // 稍後再試
                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                }
                //消費成功
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            });
            consumer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6、模擬資訊傳送

controller/OrderController.java

@RestController
@RequestMapping("/api/v1/pub")
// 功能描述:模擬微信支付回撥
public class OrderController {

    @Autowired
    private ProducerService producerService;

    // 功能描述:微信支付回撥介面
    @GetMapping("order")
    public Object order(String msg){
        // 生成訊息佇列地址
        Destination destination = new ActiveMQQueue("order.queue");
        producerService.sendMessage(destination, msg);
        return JsonData.buildSuccess("");
    }

    @GetMapping("common")
    public Object common(String msg){
        producerService.sendMessage(msg);
        return JsonData.buildSuccess("");
    }

    @GetMapping("topic")
    public Object topic(String msg){
        producerService.publish(msg);
        return JsonData.buildSuccess("");
    }

	// 以下為本節新增程式碼
	
    @Autowired
    private MsgProducer msgProducer;

    // 功能描述:微信支付回撥介面。msg是支付資訊。tag是訊息二級分類
    @GetMapping("rocketmq")
    public Object order(String msg, String tag) throws MQClientException, RemotingException, MQBrokerException, InterruptedException, UnsupportedEncodingException {

        // 建立一個訊息例項,包含 topic、tag 和 訊息體
        Message message = new Message("testTopic",tag, msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
        SendResult result = msgProducer.getProducer().send(message);
        System.out.println("傳送響應:MsgId:" + result.getMsgId() + ",傳送狀態:" + result.getSendStatus());
        return JsonData.buildSuccess("");
    }
}

7、專案測試演示

啟動程式並呼叫介面:

http://127.0.0.1:8080/api/v1/pub/rocketmq?msg=suiyi123&tag=suiyi456

在這裡插入圖片描述

對應的,如下所示:

在這裡插入圖片描述

五、總結

總結一下本節專案:

在這裡插入圖片描述

相關文章