RocketMq灰皮書(三)------MQ使用

劍小純發表於2021-02-18

RocketMq灰皮書(三)------MQ使用

在使用MQ之前,我們回顧一下前兩篇博文的內容.

  1. 我們大致瞭解了RocketMQ的四個概念,分別是:Producer,Consumer,MessageBroker
  2. 我們在本地的Windows10系統上,部署了RocketMQ和其後臺系統

在本篇博文中,我們會使用使用SpringBoot構建兩個微服務,一個作為生產者,一個作為消費者,通過RocketMQ傳遞訊息,瞭解在Java中使用RocketMQ的方法.


一. SpringBoot整合RocketMQ收發訊息

在灰皮書第一篇文章中,我畫了下面這個圖:

image-20210209115705604

現在我們本地的RocketMQ也部署起來了,接下來我們建立兩個微服務通過MQ來收發訊息,實現基本的流程.


1. 微服務構建

首先我們建立兩個基於SpringBoot的微服務,分別是:

  • rocketmq-consumer訊息消費者
  • rocketmq-producer訊息生產者

image-20210218093723919

兩個服務裡面,rocketmq-consumer的埠號是2001,rocketmq-producer的埠號是2002


2. 微服務啟動測試

分別在兩個微服務寫兩個測試方法,啟動測試:

rocketmq-consumer

@RestController
public class ConsumerController {

    @GetMapping("/consumer")
    public String index() {
        return "rocketmq-consumer";
    }

}

rocketmq-producer

@RestController
public class ProducerController {

    @GetMapping("/producer")
    public String index() {
        return "rocketmq-producer";
    }

}

啟動測試,兩個介面都成功訪問.

根據我們最上面的圖,服務A傳送訊息到服務B,在這裡,我們用rocketmq-producer來傳送訊息,訊息傳送到rocketmq以後,由服務Brocketmq-consumer消費訊息.


3. 生產者傳送訊息

使用rocketmq傳送訊息有很多種方式,因為我們使用的是SpringBoot,這裡直接使用官方提供的rocketmq-spring-boot-starter包來開發

github上有個專案:RocketMQ-Spring

它就是RocketMq官方提供的整合了SpringBoot的rocketmq工具包,git地址如下:https://github.com/apache/rocketmq-spring

當然,你也可以使用原生的rocketmq-client包,在官方的示例中,使用的就是這種方式,具體可以檢視官方文件,下面我們直接使用rocketmq-spring-boot-starter來傳送訊息.

我們可以看到有很多的版本可以用:

image-20210218100739239

這裡我們使用2.0.3這個版本吧,具體的官方細節可以檢視https://github.com/apache/rocketmq-spring/blob/release-2.0.3/README_zh_CN.md

3.1傳送String訊息

首先是pom座標:

<!--add dependency in pom.xml-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>

然後再rocketmq-producer的配置檔案中配置rocketmq的name-servergroup

## application.properties
rocketmq.name-server=127.0.0.1:9876
rocketmq.producer.group=producer

rocketmq-spring-boot-starter中提供了一個RocketMQTemplate來方便我們傳送訊息,我們可以直接注入這個類來使用.

RocketMQTemplatesend方法和convertAndSend方法,都可以用來傳送訊息,區別是,前者的方法入參是rocketmq規定的Message型別,而後者可以傳送物件,並且幫我們轉換,原始碼如下:

	/**
	 * Send a message to the given destination.
	 * @param destination the target destination
	 * @param message the message to send
	 */
	void send(D destination, Message<?> message) throws MessagingException;

	/**
	 * Convert the given Object to serialized form, possibly using a
	 * {@link org.springframework.messaging.converter.MessageConverter},
	 * wrap it as a message and send it to a default destination.
	 * @param payload the Object to use as payload
	 */
	void convertAndSend(Object payload) throws MessagingException;

下面我們直接傳送訊息到mq

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @GetMapping("/producer")
    public String index() {
        rocketMQTemplate.convertAndSend("test-topic", "訊息傳送成功!");
        return "rocketmq-producer";
    }

convertAndSend方法有兩個引數,第一個引數是訊息要傳送到的topic,也就是目的地,第二個引數就是訊息本身,至於topic到底是什麼,這個我們後面詳細來說,我們只需要知道,我們的訊息傳送到了rocketmq的一個叫做test-topic的地方即可.

並且,由於我們在灰皮書第二章的時候,啟動mq的時候,指定了autoCreateTopicEnable=true,也就是說,我們使用RocketMQTemplate傳送的訊息,就算topic之前不存在,rocket也會幫我們建立好.

編碼完成,重啟專案,我們只要訪問http://localhost:2002/producer就會傳送訊息到mq,我們可以通過rocketmq-console檢視我們傳送的訊息

可以看到mq自動為我們建立了topic:

image-20210218113616038

在message頁籤,可以檢視到我們剛才傳送的訊息:

image-20210218113722908

詳細的訊息內容:

image-20210218113741161

3.2傳送物件

在上面的例子中,我們直接傳送字串到MQ,一般來說,我們傳送的訊息體是一個java物件,在這裡也是可以的,我們改造一下程式碼:

    @GetMapping("/producer")
    public String index() {
        rocketMQTemplate.convertAndSend("test-topic", new User("張三", 20));
        return "rocketmq-producer";
    }

    @Data
    class User implements Serializable {

        private static final long serialVersionUID = -3486413003967431764L;
        private String name;
        private Integer age;



        User() {}

        User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }

這樣我們傳送了一個User物件到RocketMQ中,我們再去rocketmq-console檢視:

image-20210218145923688

可以看到,訊息成功傳送到了mq中,需要注意的是,這裡我們傳送的物件要實現Serializable介面,不然會拋異常.

那麼我們傳送的訊息的內容是怎麼序列化的呢?

RocketMQ的訊息體都是以byte[]方式儲存的,如果內容體是java.lang.String型別時,統一按照UTF-8編碼轉成byte[];如果訊息內容不是String型別的,則採用jackson-databind序列化成JSON格式的字串後,再統一按照UTF-8編碼轉換成byte[]

以上釋義源於RocketMQ官方文件,所以說,有問題多看看官方文件能很大程度上解決我們的疑惑!


4. 消費訊息

好了,我們的訊息傳送成功了,接下來我們在rocketmq-consumer應用中消費之前傳送出來的訊息.

在開發之前我們先想一下: 訊息的生產者隨著使用者的請求,不斷的往MQ中傳送訊息,那麼消費者在消費訊息的時候,是怎麼知道它要取哪一條訊息呢?

我們之前的文章中提到過一個topic,生產者在傳送訊息的時候,會指定一個topic,訊息會傳送到某個topic下,那麼自然而然的,消費者在獲取訊息的時候,也是需要知道它要從哪個topic裡面去獲取訊息的.

而獲取訊息,則是通過監聽器來完成的.

首先在rocketmq-consumer專案的配置檔案中指定mq的nameServer的地址:rocketmq.name-server=127.0.0.1:9876

建立一個監聽器:

@Component
@RocketMQMessageListener(topic = "test-topic", consumerGroup = "consumer")
@Slf4j
public class Consumerlistener implements RocketMQListener<User> {



    @Override
    public void onMessage(User message) {
        log.info("收到訊息 : {}", message);
    }


}

@RocketMQMessageListener註解中我們指定了2個引數:

  • topic 指定監聽器要監聽的topic,監聽器執行以後,會一直監聽該topic下的訊息
  • consumerGroup 指定當前消費者是資料哪個消費組,這個概念我們後面會詳細說

其次,我們自定義的監聽器還要實現RocketMQListener<T>介面,該介面的泛型型別就是我們生產者傳送訊息的訊息型別,之前我們傳送的是User物件,因此這裡也是User物件

實現RocketMQListener介面的onMessage方法,方法的入參就是我們傳送出來的訊息,在這個方法中我們可以進行自己的業務處理.

啟動服務rocketmq-consumer,可以看到正常消費到了訊息:

image-20210218155436627


以上,我們成功的在我們的微服務中使用RocketMQ進行了訊息的傳送和消費.

不僅僅是簡單的訊息,RocketMQ還支援更高階的功能,比如事務訊息訊息軌跡等,這些高階特效我們會下後面的進階文章中詳細講解.

結語:

在本篇博文中,我們使用RocketMQ官方提供的pom包進行了訊息的傳送和接收,也成功的在rocketmq-console中檢視到了訊息.

在這個工程中,我們接觸了很多新的概念:

  • topic
  • consumerGroup

以上這些概念,以及前面篇文章中遺留下來的概念,我們將在下一篇文章中詳細介紹.

個人公眾號<橙耘自留地>日前已經開通,後續博主釋出的文章都會一併更新到公眾號,如有需要,自行查閱.

關於橙耘自留地,是我個人聚焦網際網路技術棧學習分享的一個平臺,創立之初是因為目前業內各種技術課程資料層次不齊,褒貶不一,有時候一門課花費高價買入,其實內含草包,有時偶爾低價得之,卻又大有乾貨.因此我會根據大家的意見和評價,選擇不同的技術棧去學習,一為提升我自己的技術,二為大家梳理出質量比較好的課程,以作參考.同時,相關的學習心得也會一併更新到部落格和公眾號.

qrcode_for_gh_c1462e34b232_344

相關文章