rocketmq學習 實戰(三)

前言

基於前兩篇,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();
    }
  1. 發送消息是向2個節點的broker的master發送,發送使用默認的負載均衡機制,有的發向broker-a,有的發向broker-b
    在這裏插入圖片描述
  2. 因爲使用的主從結構,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_SUCCESSRECONSUME_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條,各不重複,符合預期
在這裏插入圖片描述
在這裏插入圖片描述

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