IoT MQ實現篇:組件選型與插拔式設計

IoT MQ實現篇:組件選型與插拔式設計

概述

本篇是IoT MQ內部實現篇的第一篇,實現篇主要介紹在內部設計和實現時對很複雜的功能點的設計與考慮,也是jmqtt的內部的具體實現,本篇主要介紹:

  1. 模塊化與各個組件的選型
  2. 模塊插拔式的設計

模塊化與各個組件的選型

模塊化和組件兩個概念總是在設計架構時會討論到的兩個概念,一般來說,模塊化是指功能上的拆分,將各個功能拆分爲模塊,組件化指根據模塊對於技術上的選型,所以模塊化更偏向於功能拆分,組件化更偏向於技術選型與隔離。對於Jmqtt來說,還是採用分層的架構,進行模塊化,在根據不同的層進行相應的組件技術選型:
例如,下面是Jmqtt的項目圖:
在這裏插入圖片描述
主要就是按照各個功能進行模塊化的,詳情參考:https://github.com/Cicizz/jmqtt
對於其中兩個比較重要的模塊的組件都是可插拔式的:
jmqtt-store :主要負責存儲mqtt的數據,內部實現了內存和採用rocksdb本地持久化的兩種方式
jmqtt-group :主要負責集羣通信,目前是基於netty自研的tcp集羣通信方式,對於消息中轉等,可以用mq方式直接接入,對原代碼侵入不大

在模塊化時,主要考慮的是功能分類,職責分離,在組件化技術選型和設計時,主要考慮的是插拔式,面向接口設計,並且儘量不引入外部組件,方便運維

模塊插拔式的設計

架構設計的目的主要就是確定系統的複雜性並在最初的時候就能確定解決方案,但是所有架構又是演進的,對於新的業務需求,總要在原來的系統上添磚加瓦,對於擴展性好的系統來說,新增功能需求都還好,但是如果對於設計不好,擴展性很差的系統來說,可能改的人都要頭皮發麻。插拔式設計就是很好的提高系統擴展性的設計之一,在對Jmqtt進行設計和開發時,我對於可插拔的設計主要從兩個方面考慮:

  1. 可以很方便的進行底層技術組件的替換,例如Jmqtt的存儲層可以很方便的替換成其他存儲,例如redis等等
  2. 可以很方便的進行二次開發,對於使用者來說,如何解決業務需求才是重中之中,在Jmqtt中,主要通過策略模式,命令模式,面向接口的方式,方便用戶進行二次開發。

這裏以Jmqtt的acl處理爲例,介紹如何方便的進行二次開發:

在Jmqtt中,權限主要分爲兩種:

  • 連接權限:主要校驗clientid,username,password是否合規等
  • 發佈訂閱權限:主要校驗該clientid的設備是否能向該topic發送消息或訂閱該topic

jmqtt主要設計兩個接口,用於處理校驗關係(以連接權限處理爲例):

/**
 * Connect permission manager
 */
public interface ConnectPermission {
    /**
     * Verfy the clientId whether it meets the requirements or not
     */
    boolean clientIdVerfy(String clientId);
    /**
     * if the client is on blacklist,is not allowed to connect
     */
    boolean onBlacklist(String remoteAddr,String clientId);
    /**
     * verfy the clientId,username,password whether true or not
     */
    boolean authentication(String clientId,String userName,byte[] password);
    /**
     * verfy the client's heartbeat time whether the compliance
     */
    boolean verfyHeartbeatTime(String clientId,int time);
}

使用者只需要實現該接口,並在BrokerController類中的初始化即可:

{// permission pluggable
    this.connectPermission = new DefaultConnectPermission();
    this.pubSubPermission = new DefaultPubSubPermission();
}

這裏目前還是需要使用者去修改代碼,後續可能會改成用配置項反射加載的方式,其中DefaultConnectPermission是我默認使用的一個關係權限類。

對於插拔式高可擴展性設計,除了面向接口,在Jmqtt中主要用到了:

  1. 回調鉤子,例如在消息錢處理一個鉤子,消息處理後一個鉤子

  2. 數據擴展接口:例如Jmqtt集羣數據處理,在集羣傳輸DTO中保留了一個字段:

    private HashMap<String,String> extField;
    

該字段就是爲了使用者及後續jmqtt擴展時可能會用到時預留的字段。

結語

因爲Jmqtt主要是開源項目,所以需要預留很多供二次開發的接口,但是對於內部系統而言,模塊及組件化一樣非常重要,前期設計後可以減少很多後面的工作量,一般來說,擴展設計最好的就是設計成可插拔式的。因爲自己這方面經驗也不多,這裏只簡單介紹和總結了下自己這方面的思考及自己在Jmqtt中的實際應用。

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