前言
基於前兩篇,RocketMq 學習 中文文檔(一) RocketMq 集羣搭建 部署 (2m-2s-async)我們已經瞭解了rocketmq的工作流程和集羣搭建,本文介紹java接入的代碼部分.下篇:順序消息和事務消息
目錄
1.生產者
2.消費者
3.演示一下master宕機:
4.消息重試:
5.廣播消費
6.集羣消費
正文
1.普通消費
依賴
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.3.2</version>
</dependency>
1.生產者
/**
* 普通消息生產者
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
//設置組名,並實例化
DefaultMQProducer producer = new
DefaultMQProducer("producerGroup1");
// 名稱服務,分號分割
producer.setNamesrvAddr("192.168.229.5:9876;192.168.229.6:9876");
producer.start();
for (int i = 0; i < 10; i++) {
//消息實例
Message msg = new Message("topic1" /* Topic */,
"TagA" /* Tag */,
("Hello RocketMQ " +
i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
);
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
}
producer.shutdown();
}
- 發送消息是向2個節點的broker的master發送,發送使用默認的負載均衡機制,有的發向broker-a,有的發向broker-b
- 因爲使用的主從結構,slave與master的消息同步
2.消費者
/**
* 普通消息消費者
* 採用的是Consumer Push的方式
*/
@Test
public void test2() {
//實例化消費者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup1");
consumer.setNamesrvAddr("192.168.229.5:9876;192.168.229.6:9876");
try {
//訂閱topic1下的所有tag的消息
consumer.subscribe("topic1", "*");
//註冊回調
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);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.printf("Consumer Started.%n");
while (true) {
}
} catch (MQClientException e) {
e.printStackTrace();
}
}
3.演示一下master宕機:
此刻默認是從master上消費,當master都健在時,一切正常.
此刻:把節點B的master停掉,master有一些消息未消費,則
停掉broker-b-master前(有幾條消息未被消費):
停掉broker-b-master後: b節點只有一個slave(只能從此節點消費,不能發送了)
此刻發送10條消息測試,發現broker-b節點不再接收新消息,新消息全到master活着的A節點
啓動一個消費者,消費topic1下的所有
可以看到,broker-b分片上的遺存的消息仍可被消費
主從方式保證了消息的高可用,現在是異步方式,會發生極少量消息丟失,如果業務是嚴格要求消息可用性,可使用同步刷盤,可靠性100%,性能相較異步略低,但也很高.
4.消息重試:
消息重試有兩種,1.發送失敗,2.消費失敗
4.1發送失敗
由於網絡抖動,或其他因素導致發送失敗,可以設置重試次數,在2000(超時時間範圍內)
4.1消費失敗
消息重試重要的功能在消費失敗時,有兩種失敗情況:1.timeout,2.exception,rocketmq提供兩種狀態:1. CONSUME_SUCCESS 2. RECONSUME_LATER
1.timeout
當發生超時時,消費端會一直重試,直至成功
2.exception
當發生異常時,可以控制返回狀態爲CONSUME_SUCCESS 或RECONSUME_LATER,當返回RECONSUME_LATER時,broker會保留這條消息,而消費端會根據設置的次數進行重複消費,一般重試個3次就差不多了,有個重試策略,重試間隔時間越來越長: 10s、30s、1mins、2mins等,當超過次數後,需要額外處理失敗的消息.
/**
* 普通消息消費者
*/
@Test
public void test4() {
//實例化消費者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup1");
consumer.setNamesrvAddr("192.168.229.5:9876;192.168.229.6:9876");
try {
//訂閱topic1下的所有tag的消息
consumer.subscribe("topic1", "*");
//註冊回調
consumer.registerMessageListener(new MessageListenerConcurrently() {
int count = 1;
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
try {
String body = new String(msgs.get(0).getBody(), "utf-8");
System.out.printf("%s Receive New Messages: %s %n", count++, msgs);
if ("Hello RocketMQ 3".equals(body)) {
if(msgs.get(0).getReconsumeTimes() ==4){
//TODO 超過最大重試次數後,應手動處理這條消息
}
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.printf("Consumer Started.%n");
while (true) {
}
} catch (Exception e) {
e.printStackTrace();
}
}
結果如下:
顯然,同一條消息被消費了多次,時間間隔越來越長,業務中可根據重試的次數msg.getReconsumeTimes() 來保證消息失敗時,應該手動管理這條消息了
5.廣播消費
啓動兩個客戶端即可
/**
* 普通消息消費者1
*/
@Test
public void test5() {
```此處省略代碼```
//廣播消費
consumer.setMessageModel(MessageModel.BROADCASTING);
```此處省略代碼```
System.out.printf("consumer1: %s Receive New Messages: %s %n", count++, msgs);
```此處省略代碼```
}
/**
* 普通消息消費者2
*/
@Test
public void test6() {
```此處省略代碼```
//廣播消費
consumer.setMessageModel(MessageModel.BROADCASTING);
```此處省略代碼```
System.out.printf("consumer2: %s Receive New Messages: %s %n", count++, msgs);
```此處省略代碼```
}
結果兩個節點消費情況一樣:
6.集羣消費
同上,開兩個消費端,消費模式改爲集羣 CLUSTERING,測試producer發10條消息,可以看到,consumer1+consume2兩者共消費10條,各不重複,符合預期