RocketMQ快速入門詳解

 RocketMQ是阿里巴巴在2012年開源的分佈式消息中間件,目前已經捐贈給Apache基金會,已經於2016年11月成爲 Apache 孵化項目,相信RocketMQ的未來會發揮着越來越大的作用,將有更多的開發者因此受益。

        本文僅對RocketMQ的簡單實用做入門性介紹,不對RocketMQ的底層原理進行深入介紹,後續文章將對RocketMQ的原理做詳細介紹。

        RocketMQ的Maven依賴:

   

[java] view plain copy
  1. <!-- https://mvnrepository.com/artifact/com.alibaba.rocketmq/rocketmq-client -->  
  2. <dependency>  
  3.     <groupId>com.alibaba.rocketmq</groupId>  
  4.     <artifactId>rocketmq-client</artifactId>  
  5.     <version>3.2.6</version>  
  6. </dependency>  

     MQ的消費類RocketMQConsumer.java:

    

[java] view plain copy
  1. package com.lance.rocketMQ.RocketMQ;  
  2.   
  3. import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;  
  4. import com.alibaba.rocketmq.client.consumer.listener.MessageListener;  
  5. import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;  
  6. import com.alibaba.rocketmq.client.exception.MQClientException;  
  7. import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;  
  8.   
  9. import java.util.UUID;  
  10.   
  11.   
  12. /** 
  13.  * Created by lance on 2017/2/10. 
  14.  */  
  15. public class RocketMQConsumer {  
  16.   
  17.     private DefaultMQPushConsumer consumer;  
  18.   
  19.     private MessageListener listener;  
  20.   
  21.     protected String nameServer;  
  22.   
  23.     protected String groupName;  
  24.   
  25.     protected String topics;  
  26.   
  27.     public RocketMQConsumer(MessageListener listener, String nameServer, String groupName, String topics) {  
  28.         this.listener = listener;  
  29.         this.nameServer = nameServer;  
  30.         this.groupName = groupName;  
  31.         this.topics = topics;  
  32.     }  
  33.   
  34.     public void init() {  
  35.         consumer = new DefaultMQPushConsumer(groupName);  
  36.         consumer.setNamesrvAddr(nameServer);  
  37.         try {  
  38.             consumer.subscribe(topics, "*");  
  39.         } catch (MQClientException e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.         consumer.setInstanceName(UUID.randomUUID().toString());  
  43.         consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);  
  44.         consumer.registerMessageListener((MessageListenerConcurrently) this.listener);  
  45.   
  46.         try {  
  47.             consumer.start();  
  48.         } catch (MQClientException e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.         System.out.println("RocketMQConsumer Started! group=" + consumer.getConsumerGroup() + " instance=" + consumer.getInstanceName()  
  52.         );  
  53.     }  
  54.   
  55.   
  56. }  

       MQ消息的監聽接口類RocketMQListener.java

      

        

[java] view plain copy
  1. package com.lance.rocketMQ.RocketMQ;  
  2.   
  3. import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;  
  4. import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;  
  5. import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;  
  6. import com.alibaba.rocketmq.common.message.MessageExt;  
  7.   
  8. import java.util.List;  
  9.   
  10. /** 
  11.  * Created by lance on 2017/2/10. 
  12.  */  
  13. public class RocketMQListener  implements MessageListenerConcurrently {  
  14.   
  15.   
  16.     @Override  
  17.     public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {  
  18. //        System.out.println("get data from rocketMQ:" + msgs);  
  19.         for (MessageExt message : msgs) {  
  20.   
  21.             String msg = new String(message.getBody());  
  22.             System.out.println("msg data from rocketMQ:" + msg);  
  23.         }  
  24.   
  25.         return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;  
  26.     }  
  27. }  

        MQ消息的生產者類RocketMQProducer.java

[java] view plain copy
  1. package com.lance.rocketMQ.RocketMQ;  
  2.   
  3. import com.alibaba.rocketmq.client.exception.MQClientException;  
  4. import com.alibaba.rocketmq.client.producer.DefaultMQProducer;  
  5. import com.alibaba.rocketmq.client.producer.SendResult;  
  6. import com.alibaba.rocketmq.client.producer.SendStatus;  
  7. import com.alibaba.rocketmq.common.message.Message;  
  8.   
  9. import java.util.UUID;  
  10.   
  11. /** 
  12.  * Created by lance on 2017/2/10. 
  13.  */  
  14. public class RocketMQProducer {  
  15.   
  16.     private DefaultMQProducer sender;  
  17.   
  18.     protected String nameServer;  
  19.   
  20.     protected String groupName;  
  21.   
  22.     protected String topics;  
  23.   
  24.     public void init() {  
  25.         sender = new DefaultMQProducer(groupName);  
  26.         sender.setNamesrvAddr(nameServer);  
  27.         sender.setInstanceName(UUID.randomUUID().toString());  
  28.         try {  
  29.             sender.start();  
  30.         } catch (MQClientException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34.   
  35.     public RocketMQProducer(String nameServer, String groupName, String topics) {  
  36.         this.nameServer = nameServer;  
  37.         this.groupName = groupName;  
  38.         this.topics = topics;  
  39.     }  
  40.   
  41.     public void send(Message message) {  
  42.   
  43.         message.setTopic(topics);  
  44.   
  45.         try {  
  46.             SendResult result = sender.send(message);  
  47.             SendStatus status = result.getSendStatus();  
  48.             System.out.println("messageId=" + result.getMsgId() + ", status=" + status);  
  49.         } catch (Exception e) {  
  50.             e.printStackTrace();  
  51.         }  
  52.     }  
  53. }  

       測試RocketMQ的消費 RocketMQConsumerTest.java

[java] view plain copy
  1. package com.lance.rocketMQ.RocketMQ;  
  2.   
  3. /** 
  4.  * Created by lance on 2017/2/10. 
  5.  */  
  6. public class RocketMQConsumerTest {  
  7.   
  8.   
  9.     public static void main(String[] args) {  
  10.   
  11.   
  12.         String mqNameServer = "172.10.254.2:9876";  
  13.         String mqTopics = "MQ-MSG-TOPICS-TEST";  
  14.   
  15.         String consumerMqGroupName = "CONSUMER-MQ-GROUP";  
  16.         RocketMQListener mqListener = new RocketMQListener();  
  17.         RocketMQConsumer mqConsumer = new RocketMQConsumer(mqListener, mqNameServer, consumerMqGroupName, mqTopics);  
  18.         mqConsumer.init();  
  19.   
  20.   
  21.         try {  
  22.             Thread.sleep(1000 * 60L);  
  23.         } catch (InterruptedException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.   
  27.     }  
  28. }  

          run RocketMQConsumerTest.java 之後,控制檯輸出:

       

[java] view plain copy
  1. RocketMQConsumer Started! group=CONSUMER-MQ-GROUP instance=1eb7d308-4414-4658-90b5-e2cae3b793eb  
            結果分析: 此時MQ對應的TOPIC中並沒有響應的消息,故收不到消息,僅看到MQ消費者正常啓動信息。

       

        MQ的生產者測試類:RocketMQProducerTest.java

       

[java] view plain copy
  1. package com.lance.rocketMQ.RocketMQ;  
  2.   
  3. import com.alibaba.rocketmq.common.message.Message;  
  4.   
  5. /** 
  6.  * Created by lance on 2017/2/10. 
  7.  */  
  8. public class RocketMQProducerTest {  
  9.   
  10.     public static void main(String[] args) {  
  11.   
  12.         String mqNameServer = "172.10.254.2:9876";  
  13.         String mqTopics = "MQ-MSG-TOPICS-TEST";  
  14.   
  15.         String producerMqGroupName = "PRODUCER-MQ-GROUP";  
  16.         RocketMQProducer mqProducer = new RocketMQProducer(mqNameServer, producerMqGroupName, mqTopics);  
  17.         mqProducer.init();  
  18.   
  19.   
  20.         for (int i = 0; i < 5; i++) {  
  21.   
  22.             Message message = new Message();  
  23.             message.setBody(("I send message to RocketMQ " + i).getBytes());  
  24.             mqProducer.send(message);  
  25.         }  
  26.   
  27.   
  28.   
  29.     }  
  30.   
  31. }  

          run RocketMQProducerTest.java 之後,RocketMQProducerTest.java 對應的控制檯輸出爲:

                

[java] view plain copy
  1. messageId=0A71290100002A9F00000003D0BB0832, status=SEND_OK  
  2. messageId=0A71290100002A9F00000003D0BB08BB, status=SEND_OK  
  3. messageId=0A71290100002A9F00000003D0BB0944, status=SEND_OK  
  4. messageId=0A71290100002A9F00000003D0BB09CD, status=SEND_OK  
  5. messageId=0A71290300002A9F000000005440AEED, status=SEND_OK  
         結果分析:表明所有消息都已經正常發送,且被RocketMQ正常接收。

          此時查看RocketMQConsumerTest.java對應的控制檯輸出發生改變,輸出內容變更如下:

         

[java] view plain copy
  1. RocketMQConsumer Started! group=CONSUMER-MQ-GROUP instance=1eb7d308-4414-4658-90b5-e2cae3b793eb  
  2. msg data from rocketMQ:I send message to RocketMQ 1  
  3. msg data from rocketMQ:I send message to RocketMQ 0  
  4. msg data from rocketMQ:I send message to RocketMQ 3  
  5. msg data from rocketMQ:I send message to RocketMQ 2  
  6. msg data from rocketMQ:I send message to RocketMQ 4  

看,簡單吧!


備註:小編自己使用了Apache版本的RocketMQ(即RocketMQ 4.*),發現只需要更改import的package的路徑而已,不需要修改其他代碼,請參考。


RocketMQ的重複問題解決方式:
a.MQ的消費端執行的操作具有冪等性,即無論多少次重複執行,其結果是一樣的;
b.MQ的消費端做重複校驗,比如將受到MQ消息的唯一編號保存到Redis中,即每次收到消息時,將檢查唯一編號是否已經在Redis中,如果存在說明消息重複;否則將唯一編號放入到Redis中,可以根據系統需要設置唯一編號在Redis中的過期時間,以防止Redis溢出。


 

參考鏈接:1.分佈式開放消息系統(RocketMQ)的原理與實踐 (強烈推薦)

                    2.RocketMQ捐贈給Apache那些鮮爲人知的故事

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