Spring如何實現可插拔配置?

Java3y發表於2022-12-22

大家好,我是3y,一年CRUD經驗用十年的markdown程式設計師??‍?常年被譽為職業八股文選手

我又又又又被吐槽了,隨之而來,我的訊息推送平臺開源專案Austin又又又又更新啦,迭代自己的專案多是一件美事啊

原始碼Gitee連結:gitee.com/austin

01、可插拔

我的專案逐漸成型了之後,有挺多小夥伴吐槽過我的專案太重了,依賴的中介軟體有點多。

在最開始的那一版需要強依賴MySQL/Redis/Kafka/Apollo(專案啟動就需要部署這些中介軟體),弱依賴prometheus/graylog/flink/xxl-job(想要有完整的專案體驗,就需要把這些給部署起來)。

  • MySQL是沒有人吐槽的,資料庫這種東西,可以說是後端必需的了。
  • Redis暫時還沒人吐槽,畢竟用的還是太多了,也沒有什麼強大的競品。
  • Apollo經常被吐槽能不能換成Nacos。
  • Kafka時而有人吐槽,想要支援RabbitMQ、RocketMQ。

我以前存在個觀念:在公司裡中介軟體是不會輕易替換的,現在我的程式碼已經實現了一種姿勢,感覺沒多大必要支援多種中介軟體實現,你想換就自己動手改改嘛,又不難

「“Apollo太重啦,Apollo不好用!快點支援Nacos!”」「“支援RocketMQ好不好啊”」「“能不能支援RabbitMQ?”」

對我來說並不是啥大理由,我還是覺得Apollo挺好用,足夠成熟穩定,同理Kafka亦是如此。不過當我被吐槽多了,總會懷疑自己是不是做得不夠好,也會跟身邊的大佬討論討論,有沒有必要支援一些功能。

思來想去,我變了,我又懂了

為了讓訊息推送平臺Austin易上手,我首先把Apollo做成弱依賴,可以透過配置選擇讀本地檔案還是讀配置中心(Apollo)。其實當我們使用Apollo時,即便Apollo掛了,Apollo本身就有很強的容災能力(自帶本地檔案)

其次,我把Kafka做成弱依賴,可以透過配置選擇用Guava的eventbus還是走分散式訊息佇列(Kafka),後續可能還會支援RocketMQ/RabbitMQ,感興趣的也可以在我的程式碼基礎上實現一把,蹭個pull request也很香的。

一方面是降低使用門檻而做的,另一方面是可以對具體實現進行可插拔,這是開源專案所需要的。我認為如果是公司級生產環境線上的專案,對這塊更多考慮的是異構容災(而非可插拔)。

於是乎,現在訊息推送平臺Austin預設的強依賴只剩下了MySQLRedis,其他中介軟體的都是弱依賴,要做到可插拔我是藉助配置去例項化不同的中介軟體。

當我的配置austin-mq-pipeline=eventbus時,我就不去例項化Kafka相關的生產者和消費者,轉而去初始化eventBus的生產者和消費者,那自然介面下的實現類就是為eventbus

02、支援Nacos分散式配置中心

專案已經將Nacos已經接入了!從我做專案開始,就一直有小夥伴留言是不是要支援Nacos作為分散式配置中心,為什麼偏偏就選擇Apollo。我一直錯覺以為我遇到了邪教組織了,現在Nacos都流行到這個地步了?

接入完Nacos,又發現了低版本的客戶端會導致SpringBean的懶載入失效,從而導致我的Kafka消費者失敗了,折騰了好一陣子!

03、(彩蛋)KAFKA支援TAG過濾

我的股東們是能直接用我的遠端服務的:Kafka的Topic是共享的,Group消費者也是共享的,在不修改的前提下,直接使用會帶來一個問題。

當同時有兩個或以上的股東在本地啟動了Austin,那就會爭搶消費這個Topic(相當於一個消費者組裡起了多個消費者),導致在測試下發的時候可能收不到自己除錯的訊息(被別的股東搶去了)。

要解決這個問題我第一時間的想法很簡單:不同的股東使用不同的group(相當於每個股東都會有獨立的消費者組),那不就完事了嘛?正好我的groupId生成是依賴渠道的code,改掉code就完事咯。

但這還是有問題的:每個股東有獨立的消費者組,意味著每個股東能消費整個topic的所有訊息,這又意味著股東會接受到其他股東的測試訊息(明明只想要自己測試的訊息,卻來了一條其他人發的)。

要解決這個問題,除了給每個股東一個獨立的topic,那就是根據tag過濾啦。

在Kafka實現這種效果,挺簡單的:在傳送的時候,把tag寫進Kafka的頭部,在消費前把非自身tag的訊息過濾掉就完事了

04、總結

從開始寫這個專案到現在還一直在迭代,這個過程受到了不少的吐槽。這種吐槽大多數是正向的,畢竟有人吐槽那才說明我這個專案是真的有人在用的,有人在看的。

最近有個想法:把這個系統做成是線上的,可以由各大開發者在推送訊息的時候呼叫我的介面,做成這樣一定會很有意思,面臨的挑戰和需求也會更多。那我就一直可以迭代,在這過程中一定我還能學到很多以前所不知道的東西。

這次我用@ConditionAlOnProperties這個註解來實現可插拔的配置,但其實如果是提供二方庫的形式的話,使用SPI的姿勢會更加優雅。

如果想學Java專案的,我還是強烈推薦我的開源專案訊息推送平臺Austin,可以用作畢業設計,可以用作校招,又可以看看生產環境是怎麼推送訊息的。

倉庫地址(求各位兄弟們三連喲!)

相關文章