自研 Pulsar Starter:winfun-pulsar-spring-boot-starter

不送花的程式猿發表於2021-08-31

原文:自研 Pulsar Starter:winfun-pulsar-spring-boot-starter

里程碑

版本 功能點 作者 完成
1.0.0 支援PulsarTemplate傳送訊息&支援自定義註解例項化Consumer監聽訊息 howinfun
1.1.0 支援動態開啟/關閉Consumer消費執行緒池、支援自定義配置Consuemr消費執行緒池引數 howinfun
1.2.0 支援Spring容器停止時,釋放Pulsar所有相關資源 howinfun TODO
1.3.0 支援多Pulsar資料來源 howinfun TODO

一、背景

Pulsar 作為新生代雲原生訊息佇列,越來越受到開發者的熱愛;而我們現在基本上的專案都是基於 SpringBoot 上開發的,但是我們可以發現,至今都沒有比較大眾和成熟的關於 Pulsar 的 Starter,所以我們需要自己整一個,從而避免常規使用 Pulsar API 時產生大量的重複程式碼。

二、設計思路

由於是第一版的設計,所以我們是從簡單開始,不會一開始就設計得很複雜,儘量保留 Pulsar API 原生的功能。

2.1、PulsarClient

我們都知道,不管是 Producer 還是 Consumer,都是由 PulsarClient 建立的。

當然了,PulsarClient 可以根據業務需要自定義很多引數,但是第一版的設計只會支援比較常用的引數。

我們這個元件支援下面功能點:

  • 支援 PulsarClient 引數配置外部化,引數可配置在 applicatin.properties 中。
  • 支援 applicatin.properties 提供配置提示資訊。
  • 讀取外部配置檔案,根據引數例項化 PulsarClient,並注入到 IOC 容器中。

2.2、Producer

Producer是傳送訊息的元件。

  • 這裡我們提供一個模版類,可以根據需求建立對應的 Producer 例項。
  • 支援將 Topic<->Producer 關係快取起來,避免重複建立 Producer 例項。
  • 支援同步/非同步傳送訊息。

2.3、Consumer

Consumer是消費訊息的元件。

  • 這裡我們提供一個抽象類,開發者只需要整合此實現類並實現 doReceive 方法即可,即消費訊息的邏輯方法。
  • 接著還提供一個自定義註解,自定義註解支援自定義 Consmuer 配置,例如Topic、Tenant、Namespace等。
  • 實現類加入上述自定義註解後,元件將會自動識別並且生成對應的 Consumer 例項。
  • 支援同步/執行緒池非同步消費。

三、使用例子

3.1、引入依賴

<dependency>
    <groupId>io.github.howinfun</groupId>
    <artifactId>winfun-pulsar-spring-boot-starter</artifactId>
    <version>1.1.0</version>
</dependency>

3.2、加入配置

pulsar.service-url=pulsar://127.0.0.1:6650
pulsar.tenant=winfun
pulsar.namespace=study
pulsar.operation-timeout=30
pulsar.io-threads=10
pulsar.listener-threads=10

3.3、傳送訊息

/**
 * 傳送訊息
 * @author: winfun
 **/
@RestController
@RequestMapping("msg")
public class MessageController {

    @Autowired
    private PulsarTemplate pulsarTemplate;
    @Autowired
    private PulsarProperties pulsarProperties;

    /***
     * 往指定topic傳送訊息
     * @author winfun
     * @param topic topic
     * @param msg msg
     * @return {@link String }
     **/
    @GetMapping("/{topic}/{msg}")
    public String send(@PathVariable("topic") String topic,@PathVariable("msg") String msg) throws Exception {
        this.pulsarTemplate.createBuilder().persistent(Boolean.TRUE)
                .tenant(this.pulsarProperties.getTenant())
                .namespace(this.pulsarProperties.getNamespace())
                .topic(topic)
                .send(msg);
        return "success";
    }
}

3.4、消費訊息

/**
 * @author: winfun
 * @date: 2021/8/20 8:13 下午
 **/
@Slf4j
@PulsarListener(topics = {"test-topic2"},
                threadPool = @ThreadPool(
                                        coreThreads = 2,
                                        maxCoreThreads = 3, 
                                        threadPoolName = "test-thread-pool"))
public class ConsumerListener extends BaseMessageListener {

    /**
     * 消費訊息
     * @param consumer 消費者
     * @param msg 訊息
     */
    @Override
    protected void doReceived(Consumer<String> consumer, Message<String> msg) {
        log.info("成功消費訊息:{}",msg.getValue());
        try {
            consumer.acknowledge(msg);
        } catch (PulsarClientException e) {
            e.printStackTrace();
        }
    }

    /***
     * 是否開啟非同步消費
     * @return {@link Boolean }
     **/
    @Override
    public Boolean enableAsync() {
        return Boolean.TRUE;
    }
}

四、原始碼

原始碼就不放在這裡分析了,大家可到Github上看看,如果有什麼程式碼上面的建議或意見,歡迎大家提MR。

相關文章