Sentinel控制台规则变化同步到Nacos

源码分析,当sentinel控制台修改规则时,会发送数据到UpdateGatewayRuleCommandHandler,其中WritableDataSource为null

  • com.alibaba.csp.sentinel.adapter.gateway.common.command.UpdateGatewayRuleCommandHandler
/*
 * Copyright 1999-2019 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.adapter.gateway.common.command;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.command.CommandHandler;
import com.alibaba.csp.sentinel.command.CommandRequest;
import com.alibaba.csp.sentinel.command.CommandResponse;
import com.alibaba.csp.sentinel.command.annotation.CommandMapping;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.net.URLDecoder;
import java.util.Set;

/**
 * @author Eric Zhao
 * @since 1.6.0
 */
@CommandMapping(name = "gateway/updateRules", desc = "Update gateway rules")
public class UpdateGatewayRuleCommandHandler implements CommandHandler<String> {
    private static WritableDataSource<Set<GatewayFlowRule>> gatewayFlowWds = null;

    @Override
    public CommandResponse<String> handle(CommandRequest request) {
        String data = request.getParam("data");
        if (StringUtil.isBlank(data)) {
            return CommandResponse.ofFailure(new IllegalArgumentException("Bad data"));
        }
        try {
            data = URLDecoder.decode(data, "utf-8");
        } catch (Exception e) {
            RecordLog.info("Decode gateway rule data error", e);
            return CommandResponse.ofFailure(e, "decode gateway rule data error");
        }

        RecordLog.info("[API Server] Receiving rule change (type: gateway rule): {}", data);

        String result = SUCCESS_MSG;
       Set<GatewayFlowRule> flowRules = JSON.parseObject(data, new TypeReference<Set<GatewayFlowRule>>() {
       });
        GatewayRuleManager.loadRules(flowRules);
        if (!writeToDataSource(gatewayFlowWds, flowRules)) {
            result = WRITE_DS_FAILURE_MSG;
        }
        return CommandResponse.ofSuccess(result);
    }

    /**
     * Write target value to given data source.
     *
     * @param dataSource writable data source
     * @param value target value to save
     * @param <T> value type
     * @return true if write successful or data source is empty; false if error occurs
     */
    private <T> boolean writeToDataSource(WritableDataSource<T> dataSource, T value) {
        //默认dataSource是null
        if (dataSource != null) {
            try {
                dataSource.write(value);
            } catch (Exception e) {
                RecordLog.warn("Write data source failed", e);
                return false;
            }
        }
        return true;
    }

    public synchronized static WritableDataSource<Set<GatewayFlowRule>> getWritableDataSource() {
        return gatewayFlowWds;
    }

    public synchronized static void setWritableDataSource(WritableDataSource<Set<GatewayFlowRule>> gatewayFlowWds) {
        UpdateGatewayRuleCommandHandler.gatewayFlowWds = gatewayFlowWds;
    }

    private static final String SUCCESS_MSG = "success";
    private static final String WRITE_DS_FAILURE_MSG = "partial success (write data source failed)";
}

WritableDataSource实现类只有FileWritableDataSource,那么类比实现一个NacosWritableDataSource,即可同步数据到nacos;

package com.example.config;

import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.exception.NacosException;

import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * NacosWritableDataSource
 *
 * @author: liuzhiguo
 * @date: 2021/8/27 10:54
 */
public class NacosWritableDataSource<T> implements WritableDataSource<T> {

    private final String groupId;
    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);
        return properties;
    }

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

    @Override
    public void close() throws Exception {
    }

}

给UpdateGatewayRuleCommandHandler注入WritableDataSource,可以基于SPI实现;
还可以实现接口CommandLineRunner,在项目启动后注入;

public class DataSourceInitFunc implements InitFunc {

    @Override
    public void init() throws Exception {
        System.out.println("自定义写出源NacosWritableDataSource");
        WritableDataSource<Set<GatewayFlowRule>> gatewayFlowWds = new NacosWritableDataSource<>("localhost:8848",
                "DEFAULT_GROUP",
                "gateway-start-gw-flow",
                data -> JSONObject.toJSONString(data, true));
        UpdateGatewayRuleCommandHandler.setWritableDataSource(gatewayFlowWds);
    }
}

在这里插入图片描述

sentinel控制台修改规则,即可同步到nacos

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值