RocketMQ安裝與簡單使用

寫在前面:

         

1.消息中間件的發展:

第一代以ActiveMQ爲代表,遵循JMS(java消息服務)規範                                                                                                  第二代以RabbitMQ爲代表是一個有Erlang語言開發的AMQP(高級消息隊列協議)的開源實現                                                第三代以kafka爲代表,是一代高吞吐、高可用的消息中間件,以及RocketMQ

RocketMQ的特點:

1.RocketMQ 是一款分佈式、隊列模型的消息中間件,具有以下特點:
2.能夠保證嚴格的消息順序
3.提供豐富的消息拉取模式
4.高效的訂閱者水平擴展能力
5.實時的消息訂閱機制
6.億級消息堆積能力
7.分佈式高可用的部署架構,滿足至少一次消息傳遞語義 
8.提供 docker 鏡像用於隔離測試和雲集羣部署
9.提供配置、指標和監控等功能豐富的 Dashboard
選用理由:
    a.強調集羣無單點,可擴展,任意一點高可用,水平可擴展。
    b.海量消息堆積能力,消息堆積後,寫入低延遲。
   c.支持上萬個隊列
   d.消息失敗重試機制
   e.消息可查詢
   f.開源社區活躍    

   g.成熟度(經過雙十一考驗)

RocketMQ物理部署結構:

    

rocketMQ幾個概念:

producer:消息生產者,生產者的作用就是將消息發送到 MQ,生產者本身既可以產生消息,如讀取文本信息等。也可以對外提供接口,由外部應用來調用接口,再由生產者將收到的消息發送到 MQ

producer group: 生產者組,簡單來說就是多個發送同一類消息的生產者稱之爲一個生產者組。在這裏可以不用關心,只要知道有這麼一個概念即可,Producer實例可以是多機器、單機器多進程、單進程中的多對象。Producer可以發送多個Topic。處理分佈式事務時,也需要Producer集羣提高可靠性

consumer : 消息消費者,簡單來說,消費 MQ 上的消息的應用程序就是消費者,至於消息是否進行邏輯處理,還是直接存儲到數據庫等取決於業務需要

consumer group : 消費者組,和生產者類似,消費同一類消息的多個 consumer 實例組成一個消費者組.Consumer實例 的集合。Consumer 實例可以是多機器、但機器多進程、單進程中的多對象。同一個Group中的實例,在集羣模式下,以均攤的方式消費;在廣播模式下,每個實例都全部消費。

Topic : Topic 是一種消息的邏輯分類,比如說你有訂單類的消息,也有庫存類的消息,那麼就需要進行分類,一個是訂單 Topic 存放訂單相關的消息,一個是庫存 Topic 存儲庫存相關的消息

Message : Message 是消息的載體。一個 Message 必須指定 topic,相當於寄信的地址。Message 還有一個可選的 tag 設置,以便消費端可以基於 tag 進行過濾消息。也可以添加額外的鍵值對,例如你需要一個業務 key 來查找 broker 上的消息,方便在開發過程中診斷問題

Tag : 標籤可以被認爲是對 Topic 進一步細化。一般在相同業務模塊中通過引入標籤來標記不同用途的消息

Broker : Broker 是 RocketMQ 系統的主要角色,其實就是前面一直說的 MQ。Broker 接收來自生產者的消息,儲存以及爲消費者拉取消息的請求做好準備

Name Server : Name Server 爲 producer 和 consumer 提供路由信息

Push Consumer : 應用通常向Consumer對象註冊一個Listener接口,一旦收到消息,Consumer對象立刻回調Listener接口方法。所以,所謂Push指的是客戶端內部的回調機制,並不是與服務端之間的機制

Pull Consumer : 應用通常主動調用Consumer從服務端拉消息,然後處理。這用的就是短輪詢方式了,在不同情況下,與長輪詢各有優點
 

 

1,linux安裝

        官網介紹很詳細:

         http://rocketmq.apache.org/docs/quick-start/

2,本地demo

2.1 pom.xml

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

2.2 producer

2.2.1 同步調用:

package org.equaker.cache;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;



/**
 * 同步發送消息-RocketMQ
 * @author EQuaker
 *
 */

public class SyncProducer_RocketMQ {

	
	public static void main(String[] args) throws Exception {
		//Instantiate with a producer group name.
        DefaultMQProducer producer = new
            DefaultMQProducer("group1");
        // Specify name server addresses.
        producer.setNamesrvAddr("外網ip:9876");
        //Launch the instance.
        producer.start();
        for (int i = 0; i < 10; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("topic-1" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " +
                    i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
            );
            
            
            //Call send message to deliver message to one of brokers.
            SendResult sendResult = producer.send(msg);
            System.out.printf("send result:%s%n", sendResult);
        }
        //Shut down once the producer instance is not longer in use.
        producer.shutdown();
	}
	
}

2.2.2 異步調用

package org.equaker.cache;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

/**
 * 異步發送消息-RocketMQ
 * @author EQuaker
 *
 */
public class AsyncProducer_RocketMQ {
	public static void main(String[] args) throws Exception {
		
        //Instantiate with a producer group name.
        DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
        // Specify name server addresses.
        producer.setNamesrvAddr("外網ip:9876");
        //Launch the instance.
        producer.start();
        producer.setRetryTimesWhenSendAsyncFailed(2);
        producer.setSendMsgTimeout(5000);
        for (int i = 0; i < 10; i++) {
                final int index = i;
                //Create a message instance, specifying topic, tag and message body.
                Message msg = new Message("topic-2",
                    "TagB",
                    "OrderID188",
                    "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
                producer.send(msg, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.println("send success: " + sendResult.getMsgId());
                    }
                    @Override
                    public void onException(Throwable e) {
                        System.out.printf("%-10d Exception %s %n", index, e);
                        e.printStackTrace();
                    }
                });
        }
        //Shut down once the producer instance is not longer in use.
        //Thread.sleep(3000);
        producer.shutdown();
    }
}

注意:

可能會報錯:

1         org.apache.rocketmq.client.exception.MQClientException: No route info of this topic, topic-2
See http://rocketmq.apache.org/docs/faq/ for further details. Exception org.apache.rocketmq.client.exception.MQClientException: No route info of this topic, topic-2
See http://rocketmq.apache.org/docs/faq/ for further details. 

主要是因爲rocketMQ異步發送,採用任務模式,及新線程,任務尚未完成就被producer.shutdown();

2.2.3 單向發送數據

package org.equaker.cache;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

/**
 * 單向發送消息-RocketMQ
 * 
 * @author EQuaker
 *
 */
public class OnewayProducer_RocketMQ {
	public static void main(String[] args) throws Exception {
		// Instantiate with a producer group name.
		DefaultMQProducer producer = new DefaultMQProducer("group3");
		// Specify name server addresses.
		producer.setNamesrvAddr("外網ip:9876");
		// Launch the instance.
		producer.start();
		for (int i = 0; i < 10; i++) {
			// Create a message instance, specifying topic, tag and message body.
			Message msg = new Message("topic-3" /* Topic */, "TagA" /* Tag */,
					("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
			);
			// Call send message to deliver message to one of brokers.
			producer.sendOneway(msg);

		}
		// Shut down once the producer instance is not longer in use.
		producer.shutdown();
	}
}

2.3 消費者

package org.equaker.cache;

import java.util.List;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;

public class Consumer_RocketMQ {
	
	public static void main(String[] args) throws Exception{
		// Instantiate with specified consumer group name.
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consume1");
         
        // Specify name server addresses.
        consumer.setNamesrvAddr("外網ip:9876");
        
        // Subscribe one more more topics to consume.
        consumer.subscribe("topic-3", "*");
        // Register callback to execute on arrival of messages fetched from brokers.
        consumer.registerMessageListener(new MessageListenerConcurrently() {

            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                ConsumeConcurrentlyContext context) {
                //System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
            	MessageQueue messageQueue = context.getMessageQueue();
            	System.out.println("broker name: "+messageQueue.getBrokerName());
            	System.out.println("topic name: "+messageQueue.getTopic());
            	System.out.println("msgs length: "+msgs.size());
                for(MessageExt msg : msgs) {
                	System.out.println(new String(msg.getBody()));
                }
                System.out.println("*******************");
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        //Launch the consumer instance.
        consumer.start();
        System.out.printf("Consumer Started.%n");
	}
	

}

更多操作見:http://rocketmq.apache.org/docs/simple-example/

https://github.com/apache/rocketmq/tree/master/example

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