SpringCloud二次開發-消息隊列(第一篇)


我們知道不同中間件之間存在很多差異,如RocketMQ支持定時重試,每次重試間隔逐漸增加。
Kafka,RabbitMq不支持重試。我們要做一個統一的Spring Cloud Starter
實現效果:
(1)讓Kafka,RabbitMq支持消息重試。
(2)使用不同的消息中間件時,我們不需要在maven引入不同的Jar包。

開發好後的使用效果

對於不同的中間件,我們僅需在application.yaml中改一下配置信息

// 如果想使用 rocketMq
paas:
  mq:
    rocket:
      target: 106.14.13.60
// 如果想使用 rabbitMq
paas:
  mq:
    kafka:
      target: 106.14.13.60

發送消息(ProducerServer爲我們自己的生產者)

@Autowired
private ProducerServer producerServer;
...
producerServer.send("發送的信息");

消費消息

@Component
public class OnsMessageListener implements MessageListener {

    @Override
    public String getTopic() {
        return "TOPIC";
    }

    @Override
    public String getTag() {
        return "TAG";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println("Listener正在監聽:"+message.getValueAsString());
        // 如果拋出異常,會進行重試一共重試16次:10s、30s、1min、2min …… 10min、20min、30min、1h、2h,最後放入死信隊列
    }
}

我們要考慮很多步驟要做

  • 適配不同消息隊列重試機制,如何讓Kafka,RabbitMq支持重試?如延時消息配合死信隊列,定時任務…
  • 適配不同消息隊列基本組件,如kafka有topic,但是無tag…
  • 適配不同消息隊列的消費類型集羣消費,廣播消費…

如果想實現這個效果,需要深入的瞭解這些中間件。這一章首先搭建一個項目框架。

有以下步驟

  1. 引入對應的依賴
  2. 編寫實現類
  3. 編寫配置文件讀取類 主要註解是@ConfigruationProperties
  4. 編寫自動裝配類
  5. 在resources/META-INF/spring.factories 中配置我們的自動裝配類
  6. maven install後引入依賴即可使用

實戰

首先看下項目結構
在這裏插入圖片描述
mq-starter爲我們要開發的sdk
demo爲引入mq-starter後的測試項目
開始開發吧~

  1. 引入的依賴
 <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
</dependencies>

說明:
第一個依賴 主要是爲編譯器配置的 可以根據properties 鼠標右鍵 點到用這個屬性的類上個
第二個依賴 主要是爲了自動裝配

  1. 編寫自己的功能實現類,此處爲實現producerServer.send()方法
    由於無論KafkaProducerServer還是RocketProducerServer,都是生產者,因此我們抽出一個接口
public interface ProducerServer {
    /**
     * 發送消息
     *
     * @param msg 消息內容
     * @return 消息Id
     */
    String send(String msg);
}

定義兩個實現類

public class KafkaProducerServer implements ProducerServer {

    String target;

    public KafkaProducerServer(String target) {
        this.target = target;
    }

    @Override
    public String send(String msg) {
        System.out.println("kafka ip:" + target + " msg:" + msg);
        return null;
    }
}
public class RocketProducerServer implements ProducerServer {

    String target;

    public RocketProducerServer(String target) {
        this.target = target;
    }

    @Override
    public String send(String msg) {
        System.out.println("rocket ip:" + target + " msg:" + msg);
        return null;
    }
}

  1. 編寫配置文件讀取類

demo項目中application.yaml中定義了消息隊列的配置(target ),我們要拿到demo中的配置信息,纔可以進行發送

@ConfigurationProperties(prefix = "paas.mq.kafka")
@Data
public class KafkaAutoConfigruationProperties {
    private String target;
}
@ConfigurationProperties(prefix = "paas.mq.rocket")
@Data
public class RocketAutoConfigruationProperties {
    private String target;
}

這裏我們要讀取的配置就是paas.mq.kafka.targer/paas.mq.rocket.targer的值
@ConfigurationProperties註解的作用就是讀取配置文件指定屬性的值

  1. 編寫自動裝配類
@Configuration
@EnableConfigurationProperties(KafkaAutoConfigruationProperties.class)
@ConditionalOnClass(KafkaProducerServer.class)
public class KafkaAutoConfigrution {
    @Autowired
    private KafkaAutoConfigruationProperties kafkaAutoConfigruationProperties;

    @ConditionalOnProperty("paas.mq.kafka.target")
    @Bean
    public KafkaProducerServer kafkaProducerServer() {
        return new KafkaProducerServer(kafkaAutoConfigruationProperties.getTarget());
    }
}

@Configuration
@EnableConfigurationProperties(RocketAutoConfigruationProperties.class)
@ConditionalOnClass(RocketProducerServer.class)
public class RocketAutoConfigrution {
    @Autowired
    private RocketAutoConfigruationProperties rocketAutoConfigruationProperties;

    @ConditionalOnProperty("paas.mq.rocket.target")
    @Bean
    public RocketProducerServer rocketProducerServer() {
        return new RocketProducerServer(rocketAutoConfigruationProperties.getTarget());
    }
}

4.1.@Configuration
標識本類是配置類(相當於spring中application.xml)

4.2.@EnableConfigurationProperties(AutoConfigruationProperties.class)
如果AutoConfigruationProperties中有註解@ConfigurationProperties 那麼這個類就
會被加到spring上下文的容器中,也就是可以通過@Autowire來注入

4.3.@ConditionalOnClass
當類路徑下有指定類的情況下 才進行下一步

4.4.@ConditionalOnMissingBean
當spring容器中沒有這個Bean的時候才進行下一步

4.5.@ConditionalOnProperty(“paas.mq.rocket.target”)
當配置文件存在“paas.mq.rocket.target”才進行下一步

我們僅需一個bean,無需同時存在RocketProducerServer,KafkaProducerServer。因此拋棄@ConditionalOnMissingBean,而使用@ConditionalOnProperty(“paas.mq.rocket.target”),選擇性的產生一個Bean對象。

  1. 在resources/META-INF下添加spring.factories 指定自動裝配的類也叫入口 內容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wpp.paas.foundation.autoconfigure.mq.kafka.KafkaAutoConfigrution,\
com.wpp.paas.foundation.autoconfigure.mq.rocket.RocketAutoConfigrution
  1. 現在在demo項目中直接自動注入我們的bean就ok了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章