SpringBoot(17)---SpringBoot整合RocketMQ

雨點的名字發表於2019-06-30

SpringBoot整合RocketMQ

上篇部落格講解了伺服器叢集部署RocketMQ 部落格地址:RocketMQ(2)---Docker部署RocketMQ叢集

這篇在上篇搭建好的基礎上,將SpringBoot整合RocketMQ實現生產消費。

GitHub地址: https://github.com/yudiandemingzi/SpringBootBlog

一、搭建步驟

先說下技術大致架構

SpringBoot2.1.6 + Maven3.5.4 + rocketmq4.3.0 + JDK1.8 +Lombok(外掛)

1、新增rocketmq包

     <!--注意: 這裡的版本,要和部署在伺服器上的版本號一致-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.3.0</version>
        </dependency>

2、JmsConfig(配置類)

連線RocketMQ伺服器配置類,這裡為了方便直接寫成常量。

/**
 * @Description: 安裝實際開發這裡的資訊 都是應該寫在配置裡,來讀取,這裡為了方便所以寫成常量
 */
public class JmsConfig {
    /**
     * Name Server 地址,因為是叢集部署 所以有多個用 分號 隔開
     */
    public static final String NAME_SERVER = "127.12.15.6:9876;127.12.15.6:9877";
    /**
     * 主題名稱 主題一般是伺服器設定好 而不能在程式碼裡去新建topic( 如果沒有建立好,生產者往該主題傳送訊息 會報找不到topic錯誤)
     */
    public static final String TOPIC = "topic_family";

}

3、Producer (生產者)

@Slf4j
@Component
public class Producer {
    private String producerGroup = "test_producer";
    private DefaultMQProducer producer;
    
    public Producer(){
        //示例生產者
        producer = new DefaultMQProducer(producerGroup);
        //不開啟vip通道 開通口埠會減2
        producer.setVipChannelEnabled(false);
        //繫結name server
        producer.setNamesrvAddr(JmsConfig.NAME_SERVER);
        start();
    }
    /**
     * 物件在使用之前必須要呼叫一次,只能初始化一次
     */
    public void start(){
        try {
            this.producer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }
  
    public DefaultMQProducer getProducer(){
        return this.producer;
    }
    /**
     * 一般在應用上下文,使用上下文監聽器,進行關閉
     */
    public void shutdown(){
        this.producer.shutdown();
    }
}

4、Consumer (消費者)

@Slf4j
@Component
public class Consumer {
    /**
     * 消費者實體物件
     */
    private DefaultMQPushConsumer consumer;
    /**
     * 消費者組
     */
    public static final String CONSUMER_GROUP = "test_consumer";
    /**
     *  通過建構函式 例項化物件
     */
    public Consumer() throws MQClientException {

        consumer = new DefaultMQPushConsumer(CONSUMER_GROUP);
        consumer.setNamesrvAddr(JmsConfig.NAME_SERVER);
        //消費模式:一個新的訂閱組第一次啟動從佇列的最後位置開始消費 後續再啟動接著上次消費的進度開始消費
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);

        //訂閱主題和 標籤( * 代表所有標籤)下資訊
        consumer.subscribe(JmsConfig.TOPIC, "*");

        // //註冊消費的監聽 並在此監聽中消費資訊,並返回消費的狀態資訊
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {

            // msgs中只收集同一個topic,同一個tag,並且key相同的message
            // 會把不同的訊息分別放置到不同的佇列中
                for(Message msg:msgs) {
                    try {
                        //消費者獲取訊息 這裡只輸出 不做後面邏輯處理
                        String body = new String(msg.getBody(), "utf-8");
                        log.info("消費者獲取訊息:輸出topic={},tags={},keys={},msg={}",msg.getTopic(), msg.getTags(), msg.getKeys(),body);
                        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }

                }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });
        
        consumer.start();
        System.out.println("消費者 啟動成功=======");
    }
}

大致就是這邊簡單,下面就是測試。


二、測試

先寫個測試介面進行測試。

1、Controller

@Slf4j
@RestController
public class Controller {

    @Autowired
    private Producer producer;

    private List<String> mesList;

    /**
     * 初始化訊息
     */
    public Controller() {
        mesList = new ArrayList<>();
        mesList.add("小小");
        mesList.add("爸爸");
        mesList.add("媽媽");
        mesList.add("爺爺");
        mesList.add("奶奶");

    }

    @RequestMapping("/text/rocketmq")
    public Object callback() throws Exception {
        //總共傳送五次訊息
        for (String s : mesList) {
            //建立生產資訊
            Message message = new Message(JmsConfig.TOPIC, "testtag", ("小小一家人的稱謂:" + s).getBytes());
            //傳送
            SendResult sendResult = producer.getProducer().send(message);
            log.info("輸出生產者資訊={}",sendResult);
        }
        return "成功";
    } 
}

2、測試結果

SpringBoot(17)---SpringBoot整合RocketMQ

很明顯生產傳送訊息已經成功,二消費者也成功接收了訊息!

另外我們再來看下RocketMQ控制檯是否也有消費記錄

SpringBoot(17)---SpringBoot整合RocketMQ

很明顯在控制檯這邊也會有消費記錄!

總結這邊只是簡單的整合,後面會通過RocketMQ實現分散式事務,可以用於線上實際環境中,到時候會深入講解下原始碼。




只要自己變優秀了,其他的事情才會跟著好起來(中將10)

相關文章