RocketMQ提供了強大的消息系統功能,RocketMQ提供了java客戶端,可以提供使用。下面代碼來自RocketMQ4.0.0中的example代碼。
Producer消息生產端:
public class Producer {
public static void main(String[] args) {
// 創建一個Produer Group
DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
// 指定NameServer地址
producer.setNamesrvAddr("192.168.1.163:9876");
try {
// 啓動producer
producer.start();
// 創建一個Message ,並指定topic、Tag和消息主體
Message msg = new Message("ZZZZWWWW", "TagA",
("Hello RocketMQ ").getBytes(RemotingHelper.DEFAULT_CHARSET));
//向broker發送一個消息
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
} catch (MQClientException | UnsupportedEncodingException e) {
e.printStackTrace();
} catch (RemotingException e) {
e.printStackTrace();
} catch (MQBrokerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
//當produer不再使用時,關閉produer
producer.shutdown();
}
}
Consumer消息消費端代碼:
public class Consumer {
public static void main(String[] args) throws InterruptedException, MQClientException {
//指定一個Consumer Group 來創建一個consumer
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name");
//指定NameServer 地址,consumer和NameServer建立長鏈接,並且獲取topic信息以及broker的ip和地址
consumer.setNamesrvAddr("192.168.1.163:9876");
//指定消費offset的位置。TIMESTAMP表示從consumer建立後,producer向broker新發送的消息開始
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
//指定消費topic,和過濾的TAG
consumer.subscribe("ZZZZWWWW", "*");
//註冊一個回調函數,當comsumer接收到消息時,執行的動作
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf(Thread.currentThread().getName() + " Receive New Messages: " + msgs + "%n");
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//啓動comsumer實例
consumer.start();
System.out.printf("Consumer Started.%n");
}
}
代碼分析:
在Consumer端註冊了一個MessageListener 接口實現,當Consumer端接收到異步分發的消息後,會執行MessageListener中的方法。
MessageListener提供了MessageListenerConcurrently 和MessageListenerOrderly 兩種策略。
根據MessageListenerConcurrently 和MessageListenerOrderly兩種策略,當pull到消息後,消息會被push到ConsumeMessageConcurrentlyService 和ConsumeMessageOrderlyService 被消費掉。
1、ConsumeMessageConcurrentlyService ,其實內部爲一個ThreadPoolExecutor線程池,每一個Message會被轉換成一個任務class ConsumeRequest implements Runnable .ConsumerRequest Task 會提交到ThreadPoolExecutor中等待被並行執行。
在ConsumerMessageConcurrentlyService 內部,會根據ConsumeConcurrentlyStatus 處理狀態的結果,來繼續處理後續的事情processConsumeResult。
2、ConsumerMessageOrderlyService 裏面也是一個線程緩存池,在ConsumerRequest Task任務中對每一個MessageQueue進行加鎖,從而保證順序消費。
同時,processConsumeResult也會處理消費失敗的情況。