nacos和sentinel配置修改互通

nacos作爲一款註冊中心,簡直牛皮到爆,它還可以作用遠程配置中心使用,並且不用環境的相同配置參數可以使用namespace隔離開來,開起來非常優雅、直觀。附nacos官網地址:https://nacos.io/zh-cn/docs/quick-start.html,我們也習慣將接口的限流規則配置放到nacos上面去,因爲nacos可以持久化,這讓我們開發者很有安全感,但是由於他是一個配置的方式存在:

                    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    

當我們修改限流規則的時候,很容易出錯,導致格式或者字母寫錯,這個時候sentinel-darshboard就派上用場了,sentinel-darshboard是一款可視化的限流服務端,我們可以很清楚的看到哪個服務的哪個接口的限流規則、熔斷規則等,但是sentinel-darshboard是以內存存儲數據的,一旦重啓,那限流規則就會失效,我們又要重新修改,所以我們就要將sentinel-darshboard修改過的數據同步到nacos持久化,這樣規則就不會丟失。

修改思路:sentinel-darshboard已經爲我們做了這個操作,剩下的就是我們改造一下客戶端就可以了,大致思路爲

​​​​​​​

修改服務端規則push修改信息到sentinel客戶端尋找對應的WritableDataSource開始本地內存修改客戶端接受信息解析並推送給nacos

sentinel做爲一款限流產品,它是由客服端和服務端的,sentinel和網關gateway一起用的時候,在gateway服務引入sentinel的客戶端依賴,並在yml配置文件中指向sentinel的服務端地址 spring.cloud.sentinel.dashboard=ip:port ,這樣當你修改限流規則的時候,相關信息就會推送到sentinel-darshboard服務端去,sentinel-darshboard是可視化的springboot項目,啓動之後用賬號密碼登錄後是一個空的ui,只有在你訪問過一次接口之後纔會出現對應的服務的相關接口限流信息:

    ​​​​​​​    ​​​​​​​    ​​​​​​​    ​​​​​​​    

當我們點擊編輯,修改限流規則的時候,sentinel服務端除了更新本地內存中的規則,還會進行一個push的操作,就是將修改後的信息推給客戶端,走的是http請求,客戶端則使用CommandHandler接收並處理請求,限流規則使用的是實現類ModifyRulesCommandHandler主要解析源碼爲:

if (FLOW_RULE_TYPE.equalsIgnoreCase(type)) {
    List<FlowRule> flowRules = JSONArray.parseArray(data, FlowRule.class);
    FlowRuleManager.loadRules(flowRules);
    if (!writeToDataSource(getFlowDataSource(), flowRules)) {
        result = WRITE_DS_FAILURE_MSG;
    }
    return CommandResponse.ofSuccess(result);
}

主要看getFlowDataSource()方法,這個方法就是獲取對應WritableDataSource實現類,實現將推送的數據推到哪裏去,但是客戶端是沒有爲我們實現這個操作的,需要我們自己實現對應的WritableDataSource,將數據推到指定的地方。我這邊自己實現的類:

public class NacosWritableDataSource<T> implements WritableDataSource<T> {


    //客戶端所處的group對應DEFAULT_GROUP
    private final String groupId;
    //客戶端所處的dataId對應
    private final String dataId;
    //客戶端所處的服務地址
    private final String serverAddr;
    private ConfigService configService;
    private final Converter<T, String> configEncoder;
    //加鎖,防止多個修改參數被後改的覆蓋,公平鎖排隊
    private final Lock lock;
    public NacosWritableDataSource(String serverAddr, String groupId, String dataId, Converter<T, String> configEncoder) {
        this.lock = new ReentrantLock(true);
        this.serverAddr = serverAddr;
        this.groupId = groupId;
        this.dataId = dataId;
        this.configEncoder = configEncoder;
        initConfigService();
    }

    private void initConfigService() {
        try {
            this.configService = NacosFactory.createConfigService(buildProperties(serverAddr));

        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

    private static Properties buildProperties(String serverAddr) {
        Properties properties = new Properties();
        properties.setProperty("serverAddr", serverAddr);
        int pos = GatewayApplication.namespace.indexOf("=");
        String namespace = GatewayApplication.namespace.substring(pos+1);
        properties.setProperty("namespace", namespace);
        return properties;
    }

    @Override
    public void write(T t) throws Exception {
        this.lock.lock();
        try {
            //String dataId, String group, String content, String casMd5, String type
            configService.publishConfig(dataId, groupId, this.configEncoder.convert(t),ConfigType.JSON.getType());
        } finally {
            this.lock.unlock();
        }
    }

    @Override
    public void close() throws Exception {
    }

}

這裏解釋一下properties.setProperty("namespace", namespace);因爲我們啓動時使用的是命令行參數指定明明空間,如果不用上述方式獲取命名空間,那修改的規則就不會推到指定的namespace下面,二是推到了默認的public去了。

要加載上述類有兩種方式:1、實現類CommandLineRunner類,在程序一起動的時候就加載此類。2、使用SPI機制加載此類,我使用的是第二種

寫一個類實現sentinel的InitFunc這個類,這個類的所有實現類都會加載,具體的實現方式是:在resources文件夾下新建目錄META-INF/services文件夾,在文件夾下面創建一個名字爲com.alibaba.csp.sentinel.init.InitFunc類型爲spring.factories的文件,文件裏面寫上InitFunc實現類的全限定名

WritableDataSourceRegistry.registerFlowDataSource(gatewayFlowWds);

這句代碼極爲重要,這句對應上文的getFlowDataSource()這個方法,這裏存,上文取。

然後剩下的就是愉快的修改sentinel-darshboard的限流規則了,刷新nacos的配置,看到規則有更新到。

網上有還有一種是修改sentinel-darshboard的源碼,個人不建議這麼做,那樣複雜還不好理解,sentinel-darshboard已經爲我們做了push的操作,我們只需要擴展一下sentinel的客戶端即可,不需要其他的操作,而且這種方法也是極爲簡單直觀的。

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