RocketMQ(01)——簡介

RocketMQ簡介

筆者使用的是Apache RocketMQ,官網是http://rocketmq.apache.org/。RocketMQ是Alibaba開源的一個分佈式消息隊列,可以通過http://rocketmq.apache.org/dowloading/releases/下載當前最新的版本。下載後解壓縮,然後通過bin/mqnamesrv啓動一個Name Server,它默認監聽在9876端口。然後需要通過bin/mqbroker -n localhost:9876啓動一個Broker,並把它註冊到剛剛啓動的那個Name Server上,Broker默認監聽在端口10911上。生產者和消費者都是跟Broker打交道,但是它們不會直接指定Broker的地址,而是通過Name Server來間接的獲取Broker的地址。這樣做的好處是可以動態的增加Broker,多個Broker之間可以組成一個集羣。應用中使用RocketMQ時需要添加RocketMQ Client依賴。

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.5.0</version>
</dependency>

然後可以通過DefaultMQProducer進行消息的發送,每一個生產者必須指定一個Group,下面代碼就指定了Group爲group1。相同處理邏輯的生產者必須定義相同的Group。這個Group只對於發送事務消息的生產者有用。然後需要通過setNamesrvAddr()指定Name Server的地址。在發送消息前必須調用其start()。發送的消息是通過org.apache.rocketmq.common.message.Message對象表示的。它必須要指定一個Topic,RocketMQ是通過抽象的Topic來管理一組隊列的,這個Topic必須在Broker中進行創建。可以通過bin/mqadmin updateTopic -b localhost:10911 -t topic1在本地剛剛啓動的Broker上創建名爲topic1的Topic。它默認擁有8個讀隊列,8個寫隊列。下面的代碼指定了消息都將發送到名爲topic1的Topic。通過其send()進行消息發送,它是同步發送的,發送完後會返回一個SendResult。其SendStatus爲SEND_OK時表示發送成功。下面的代碼一共發送了10條消息到topic1,消息內容分別是hello0…hello9。

@Test
public void testSend() throws Exception {
  //指定Producer的Group爲group1
  DefaultMQProducer producer = new DefaultMQProducer("group1");
  //指定需要連接的Name Server
  producer.setNamesrvAddr(nameServer);
  //發送消息前必須調用start(),其內部會進行一些初始化工作。
  producer.start();
  for (int i = 0; i < 10; i++) {
    //指定消息發送的Topic是topic1。
    Message message = new Message("topic1", ("hello" + i).getBytes());
    //同步發送,發送成功後纔會返回
    SendResult sendResult = producer.send(message);
    if (sendResult.getSendStatus() == SendStatus.SEND_OK) {
      System.out.println("消息發送成功:" + sendResult);
    } else {
      System.out.println("消息發送失敗:" + sendResult);
    }
  }
  //使用完畢後需要把Producer關閉,以釋放相應的資源
  producer.shutdown();
}

消息的消費者可以通過DefaultMQPushConsumer進行消費。DefaultMQPushConsumer是進行推模式消費的,它也需要指定一個Group。默認情況下相同Group的消費者將對同一個隊列中的消息進行集羣消費,即同一條消息只會被一個Consumer實例進行消費。DefaultMQPushConsumer也需要通過setNamesrvAddr()指定需要連接的Name Server。通過subscribe()指定需要消費的Topic和對應的Tag。下面指定了需要消費的Topic是topic1,通過*指定將消費所有的Tag。Tag是用來對消息進行分類標記的,需要在發送消息的時候指定。通過registerMessageListener()註冊消息監聽器,當收到消息後會回調它。下面代碼註冊的是一個MessageListenerConcurrently類型的監聽器。消息正常消費後需要返回CONSUME_SUCCESS,如果消費失敗可以返回RECONSUME_LATER,這樣可以先跳過這一條消息的消費,Broker會過一段時間再投遞這一條消息。Consumer也是需要通過start()進行啓動。這樣消費者就可以開始進行消息消費了,默認只有它啓動之後發送的消息才能收到。

@Test
public void testConsumer() throws Exception {
  //創建Consumer並指定消費者組。
  DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_group1");
  //指定需要連接的Name Server
  consumer.setNamesrvAddr(nameServer);
  //訂閱topic1上的所有Tag。
  consumer.subscribe("topic1", "*");
  //註冊一個消息監聽器
  consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
      System.out.println(Thread.currentThread().getName() + "收到了消息,數量是:" + msgs.size());
      AtomicInteger counter = new AtomicInteger();
      msgs.forEach(msg -> System.out.println(counter.incrementAndGet() + ".消息內容是:" + new String(msg.getBody())));
      return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
  });
  //啓動消費者
  consumer.start();
  //爲了確保Junit線程不立即死掉。
  TimeUnit.SECONDS.sleep(120);
}

(注:本文是基於Apache RocketMQ4.5.0所寫)

發佈了266 篇原創文章 · 獲贊 175 · 訪問量 178萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章