springboot整合rocketmq實現順序消費

消息隊列已然成爲當下非常火熱的中間件,而rocketmq作爲阿里開源的中間件產品,歷經數次超大併發的考驗,已然成爲中間件產品的首選。而有時候我們在使用消息隊列的時候,往往需要能夠保證消息的順序消費,而rocketmq是可以支持消息的順序消費的。rocketmq在發送消息的時候,是將消息發送到不同的隊列(queue,也有人稱之爲分區)中,然後消費端從多個隊列中讀取消息進行消費,很明顯,在這種全局模式下,是無法實現順序消費的。爲了實現順序消費,我們需要把有順序的消息按照他的順序,將他們發送到同一個queue中,這樣消費端在消費的時候,就保證了其順序。但是順序消費的性能肯定也相對差一些,因爲只能使用一個隊列。

好了,接下來我們使用springboot來看一下順序消費是如何實現的。 官網上給出了一個順序消費的案例,但是都是通過main方法的形式演示的(http://rocketmq.apache.org/docs/order-example/)。

一. 添加依賴:

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

 

二. 配置rocketmq地址(需要先自己搭建好rocketmq服務)

在application.yml中配置:

rocketmq:
  name-server: 192.168.1.11:9876;192.168.1.12:9876;192.168.1.13:9876
  producer:
    group: my-group1
    sendMessageTimeout: 300000

這裏我使用的rocketmq的集羣,如果是單機版,name-server只寫一個地址即可

三. 一個簡單的生產消費案例:

我們使用controller 來下一個生產者,這樣當我通過瀏覽器發起請求是,就調用生產者來生產一條消息,同時寫一個消費者,來監聽對應的消息,實現消費

生產者代碼:

@RestController
@RequestMapping("/mq")
@Slf4j
public class ProducerController {

    @Resource
    private RocketMQTemplate rocketMQTemplate;


    @RequestMapping("/sync/send1")
    public String syncSendString(){
        //發送一個同步 消息,會返回值 ---發送到 stringTopic主題
        SendResult sendResult = rocketMQTemplate.syncSend("topicTest", "Hello, World!");
        System.out.printf("syncSend1 to topic %s sendResult=%s %n", stringTopic, sendResult);
        //consumer result:------- StringConsumerNewNS received: Hello, World!
        return sendResult.toString();
    }


}

上面的案例,就是我向"topicTest" 的主題中發送一個 Hello,World  的字符串

消費者代碼:

/**
 * RocketMQMessageListener
 */
@Service
@RocketMQMessageListener(nameServer = "${rocketmq.nameserver}", topic = "topicTest", consumerGroup = "string_consumer")
public class StringConsumerNewNS implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        System.out.printf("------- StringConsumerNewNS received: %s \n", message);
    }
}

這個消費者需要綁定nameserver, 然後監聽 topicTest  這個主題。要注意,要把這個消費者放到能夠被spring容器掃描到的地方。

接下來啓動服務: 在瀏覽器訪問: localhost:{your port}/mq/sync/send1 此時就會生產出一條消息,觀察控制檯,就會看到Hello, World打印出來,代表消息消費成功

 

四. 實現順序消費

生產者: 此時要生產多條消息,方便觀察順序,我們依然寫一個controller

/**************驗證rocketmq順序消費***************/
    @RequestMapping("/send/ordered")
    public String sendOrderedMsg(){
        /**
         * hashKey: 爲了保證報到同一個隊列中,將消息發送到orderTopic主題上
         */
        rocketMQTemplate.syncSendOrderly("orderTopic","no1","order");
        rocketMQTemplate.syncSendOrderly("orderTopic","no2","order");
        rocketMQTemplate.syncSendOrderly("orderTopic","no3","order");
        rocketMQTemplate.syncSendOrderly("orderTopic","no4","order");
        return "success";
    }

這裏要注意,我是向 orderTopic主題發送4條消息,內容分別是 no1 no2 no3 no4. 第三個參數是order ,他的作用是會根據他的hash值計算髮送到哪一個隊列,我用的是同一個值order,那麼他們的hash一樣就可以保證發送到同一個隊列裏

 

消費者。要注意,消費者在消費的時候,默認是異步多線程消費的,所以無法保證順序,我們要指定同步消費纔行;先看代碼:

/**
 * 監聽順序消息,保證順序繳費
 */
@Component
@Slf4j
@RocketMQMessageListener(topic = "orderTopic", consumerGroup = "ordered-consumer",consumeMode = ConsumeMode.ORDERLY)

public class OrderedMsqConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        log.info("consumer 順序消費,收到消息{}",message);
    }
}

這裏邊指定了  consumeMode = ConsumeMode.ORDERLY, 默認值是  consumeMode = ConsumeMode.CONCURRENT

修改完畢後,啓動項目;

瀏覽器訪問:http://localhost:8888/mq/send/ordered

觀察控制檯日誌,順序打印:  no1  no2   no3   no4

好了實現了順序消費;相關源碼已上傳至github: https://github.com/lsqingfeng/action/  (springboot分支)歡迎大家關注交流

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章