Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos


1. 接着上一篇

简单创建一个SpringCloud2021.0.3项目(四)

讲到了Sentinel从Nacos拿配置

2. 思路

  1. 搜了很多教程,有不用改源码的也有要修改源码。自测不用修改源码方式还是不行,修改源码方式,可能版本不一样导致修改失效。
  2. 找到官方的解答,Sentinel 控制台(集群流控管理)
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图
  3. 只要实现推送规则就行
  4. 在本地内存修改成功后,做我们自定义推送
  5. 请求进入那个接口,页面F12修改、添加、删除后看看url是什么
  6. 这里只测试修改限流和熔断降级,热点、授权、系统的没有做

3. 下载Sentinel源码

1.8.3版本页面:https://github.com/alibaba/Sentinel/releases/1.8.3
下载链接:https://github.com/alibaba/Sentinel/archive/refs/tags/1.8.3.zip

4. 看Gateway里面读取的配置信息

Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图1
Nacos上面的配置
Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图2

5. 修改Sentinel控制台源码

  1. 修改sentinel-dashboard模块的依赖,sentinel-datasource-nacos
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图3
  2. 添加配置参数,sentinel-dashboard模块的Sentinel-1.8.3sentinel-dashboardsrcmainresourcesapplication.properties
    端口看自己情况用默认8080还是自定义
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图4
  3. 添加包com.alibaba.csp.sentinel.dashboard.rule.nacos
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图5
    在test下面官方给了一些例子,可以拷贝到main里面,也可以用我下面的代码,都会放上来
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图6
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图7
  4. 添加配置类NacosPropertiesConfiguration,读取第2步设置的参数
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图8
点击查看代码
package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "sentinel.nacos")
public class NacosPropertiesConfiguration {
    private String serverAddr;
    private String degradeRuleDataId;
    private String flowRuleDataId;
    private String groupId = "SENTINEL_GROUP";
    private String namespace;
    private String username;
    private String password;

    public String getServerAddr() {
        return serverAddr;
    }

    public void setServerAddr(String serverAddr) {
        this.serverAddr = serverAddr;
    }

    public String getDegradeRuleDataId() {
        return degradeRuleDataId;
    }

    public void setDegradeRuleDataId(String degradeRuleDataId) {
        this.degradeRuleDataId = degradeRuleDataId;
    }

    public String getFlowRuleDataId() {
        return flowRuleDataId;
    }

    public void setFlowRuleDataId(String flowRuleDataId) {
        this.flowRuleDataId = flowRuleDataId;
    }

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }

    public String getNamespace() {
        return namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
  1. 修改NacosConfig
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图9
点击查看代码
/*
 * Copyright 1999-2018 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
 *
 *      http://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.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Properties;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@EnableConfigurationProperties(NacosPropertiesConfiguration.class)
@Configuration
public class NacosConfig {

    @Bean
    public Converter, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter, String> degradeRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    // 以前的
//    @Bean
//    public ConfigService nacosConfigService() throws Exception {
//        return ConfigFactory.createConfigService("localhost");
//    }

    // 改造后的
    @Bean
    public ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration)
            throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, nacosPropertiesConfiguration.getServerAddr());
        properties.put(PropertyKeyConst.NAMESPACE, nacosPropertiesConfiguration.getNamespace());
        properties.put(PropertyKeyConst.USERNAME, nacosPropertiesConfiguration.getUsername());
        properties.put(PropertyKeyConst.PASSWORD, nacosPropertiesConfiguration.getPassword());
        return ConfigFactory.createConfigService(properties);
    }
}
  1. 修改FlowRuleNacosPublisher
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图10
点击查看代码
/*
 * Copyright 1999-2018 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
 *
 *      http://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.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter, String> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public void publish(String app, List rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(nacosPropertiesConfiguration.getFlowRuleDataId(),
                nacosPropertiesConfiguration.getGroupId(), converter.convert(rules));
    }
}
  1. 添加DegradeRuleNacosPublisher,把FlowRuleNacosPublisher复制修改下类名
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图11
点击查看代码
/*
 * Copyright 1999-2018 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
 *
 *      http://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.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
@Component("degradeRuleNacosPublisher")
public class DegradeRuleNacosPublisher implements DynamicRulePublisher> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter, String> converter;
    @Autowired
    private NacosPropertiesConfiguration nacosPropertiesConfiguration;

    @Override
    public void publish(String app, List rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(nacosPropertiesConfiguration.getDegradeRuleDataId(),
                nacosPropertiesConfiguration.getGroupId(), converter.convert(rules));
    }
}
  1. 修改熔断规则推送到Nacos,我这里熔断规则都请求这个类DegradeController,自己的看看是否也是
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图12
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图13
修改后的com.alibaba.csp.sentinel.dashboard.controller.DegradeController类
/*
 * Copyright 1999-2018 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
 *
 *      http://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.dashboard.controller;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * Controller regarding APIs of degrade rules. Refactored since 1.8.0.
 *
 * @author Carpenter Lee
 * @author Eric Zhao
 */
@RestController
@RequestMapping("/degrade")
public class DegradeController {

    private final Logger logger = LoggerFactory.getLogger(DegradeController.class);

    @Autowired
    private RuleRepository repository;
    @Autowired
    private SentinelApiClient sentinelApiClient;

    @Autowired
    @Qualifier("degradeRuleNacosPublisher")
    private DynamicRulePublisher> degradeRulePublisher;

    @GetMapping("/rules.json")
    @AuthAction(PrivilegeType.READ_RULE)
    public Result> apiQueryMachineRules(String app, String ip, Integer port) {
        if (StringUtil.isEmpty(app)) {
            return Result.ofFail(-1, "app can't be null or empty");
        }
        if (StringUtil.isEmpty(ip)) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (port == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        try {
            List rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("queryApps error:", throwable);
            return Result.ofThrowable(-1, throwable);
        }
    }

    @PostMapping("/rule")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result apiAddRule(@RequestBody DegradeRuleEntity entity) {
        Result checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }
        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);
        try {
            entity = repository.save(entity);
        } catch (Throwable t) {
            logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
            return Result.ofThrowable(-1, t);
        }
        if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", entity.getApp());
        }
        return Result.ofSuccess(entity);
    }

    @PutMapping("/rule/{id}")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result apiUpdateRule(@PathVariable("id") Long id,
                                                   @RequestBody DegradeRuleEntity entity) {
        if (id == null || id  checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }

        entity.setGmtCreate(oldEntity.getGmtCreate());
        entity.setGmtModified(new Date());
        try {
            entity = repository.save(entity);
        } catch (Throwable t) {
            logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
            return Result.ofThrowable(-1, t);
        }
        if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", entity.getApp());
        }
        return Result.ofSuccess(entity);
    }

    @DeleteMapping("/rule/{id}")
    @AuthAction(PrivilegeType.DELETE_RULE)
    public Result delete(@PathVariable("id") Long id) {
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }

        DegradeRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofSuccess(null);
        }

        try {
            repository.delete(id);
        } catch (Throwable throwable) {
            logger.error("Failed to delete degrade rule, id={}", id, throwable);
            return Result.ofThrowable(-1, throwable);
        }
        if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
            logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
        }
        return Result.ofSuccess(id);
    }

    private boolean publishRules(String app, String ip, Integer port) {
        List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        // 修改前
//        return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
        // 修改后
        boolean b = sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
        if (b) {
            try {
                degradeRulePublisher.publish(app, rules);
            } catch (Exception e) {
                logger.error("推送熔断策略到Nacos失败, app={}, rule={}", app, rules, e);
            }
        }
        return b;
    }

    private  Result checkEntityInternal(DegradeRuleEntity entity) {
        if (StringUtil.isBlank(entity.getApp())) {
            return Result.ofFail(-1, "app can't be blank");
        }
        if (StringUtil.isBlank(entity.getIp())) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (entity.getPort() == null || entity.getPort()  RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
            return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy);
        }
        if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount()  1) {
                return Result.ofFail(-1, "SlowRatioThreshold should be in range: [0.0, 1.0]");
            }
        } else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
            if (threshold > 1) {
                return Result.ofFail(-1, "Ratio threshold should be in range: [0.0, 1.0]");
            }
        }
        return null;
    }
}
  1. 修改限流规则推送到Nacos,我这里熔断规则都请求这个类FlowControllerV1,自己的看看是否也是
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图14
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图15
修改后的com.alibaba.csp.sentinel.dashboard.controller.FlowControllerV1类
/*
 * Copyright 1999-2018 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
 *
 *      http://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.dashboard.controller;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.util.StringUtil;

import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Flow rule controller.
 *
 * @author leyou
 * @author Eric Zhao
 */
@RestController
@RequestMapping(value = "/v1/flow")
public class FlowControllerV1 {

    private final Logger logger = LoggerFactory.getLogger(FlowControllerV1.class);

    @Autowired
    private InMemoryRuleRepositoryAdapter repository;

    @Autowired
    private SentinelApiClient sentinelApiClient;

    @Autowired
    @Qualifier("flowRuleNacosPublisher")
    private DynamicRulePublisher> flowRulePublisher;

    @GetMapping("/rules")
    @AuthAction(PrivilegeType.READ_RULE)
    public Result> apiQueryMachineRules(@RequestParam String app, @RequestParam String ip, @RequestParam Integer port) {

        if (StringUtil.isEmpty(app)) {
            return Result.ofFail(-1, "app can't be null or empty");
        }
        if (StringUtil.isEmpty(ip)) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (port == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        try {
            List rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("Error when querying flow rules", throwable);
            return Result.ofThrowable(-1, throwable);
        }
    }

    private  Result checkEntityInternal(FlowRuleEntity entity) {
        if (StringUtil.isBlank(entity.getApp())) {
            return Result.ofFail(-1, "app can't be null or empty");
        }
        if (StringUtil.isBlank(entity.getIp())) {
            return Result.ofFail(-1, "ip can't be null or empty");
        }
        if (entity.getPort() == null) {
            return Result.ofFail(-1, "port can't be null");
        }
        if (StringUtil.isBlank(entity.getLimitApp())) {
            return Result.ofFail(-1, "limitApp can't be null or empty");
        }
        if (StringUtil.isBlank(entity.getResource())) {
            return Result.ofFail(-1, "resource can't be null or empty");
        }
        if (entity.getGrade() == null) {
            return Result.ofFail(-1, "grade can't be null");
        }
        if (entity.getGrade() != 0 && entity.getGrade() != 1) {
            return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
        }
        if (entity.getCount() == null || entity.getCount()  apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
        Result checkResult = checkEntityInternal(entity);
        if (checkResult != null) {
            return checkResult;
        }
        entity.setId(null);
        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);
        entity.setLimitApp(entity.getLimitApp().trim());
        entity.setResource(entity.getResource().trim());
        try {
            entity = repository.save(entity);

            publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
            return Result.ofSuccess(entity);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
            return Result.ofFail(-1, e.getMessage());
        }
    }

    @PutMapping("/save.json")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result apiUpdateFlowRule(Long id, String app,
                                                  String limitApp, String resource, Integer grade,
                                                  Double count, Integer strategy, String refResource,
                                                  Integer controlBehavior, Integer warmUpPeriodSec,
                                                  Integer maxQueueingTimeMs) {
        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }
        FlowRuleEntity entity = repository.findById(id);
        if (entity == null) {
            return Result.ofFail(-1, "id " + id + " dose not exist");
        }
        if (StringUtil.isNotBlank(app)) {
            entity.setApp(app.trim());
        }
        if (StringUtil.isNotBlank(limitApp)) {
            entity.setLimitApp(limitApp.trim());
        }
        if (StringUtil.isNotBlank(resource)) {
            entity.setResource(resource.trim());
        }
        if (grade != null) {
            if (grade != 0 && grade != 1) {
                return Result.ofFail(-1, "grade must be 0 or 1, but " + grade + " got");
            }
            entity.setGrade(grade);
        }
        if (count != null) {
            entity.setCount(count);
        }
        if (strategy != null) {
            if (strategy != 0 && strategy != 1 && strategy != 2) {
                return Result.ofFail(-1, "strategy must be in [0, 1, 2], but " + strategy + " got");
            }
            entity.setStrategy(strategy);
            if (strategy != 0) {
                if (StringUtil.isBlank(refResource)) {
                    return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
                }
                entity.setRefResource(refResource.trim());
            }
        }
        if (controlBehavior != null) {
            if (controlBehavior != 0 && controlBehavior != 1 && controlBehavior != 2) {
                return Result.ofFail(-1, "controlBehavior must be in [0, 1, 2], but " + controlBehavior + " got");
            }
            if (controlBehavior == 1 && warmUpPeriodSec == null) {
                return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
            }
            if (controlBehavior == 2 && maxQueueingTimeMs == null) {
                return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
            }
            entity.setControlBehavior(controlBehavior);
            if (warmUpPeriodSec != null) {
                entity.setWarmUpPeriodSec(warmUpPeriodSec);
            }
            if (maxQueueingTimeMs != null) {
                entity.setMaxQueueingTimeMs(maxQueueingTimeMs);
            }
        }
        Date date = new Date();
        entity.setGmtModified(date);
        try {
            entity = repository.save(entity);
            if (entity == null) {
                return Result.ofFail(-1, "save entity fail: null");
            }

            publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
            return Result.ofSuccess(entity);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Error when updating flow rules, app={}, ip={}, ruleId={}", entity.getApp(),
                entity.getIp(), id, e);
            return Result.ofFail(-1, e.getMessage());
        }
    }

    @DeleteMapping("/delete.json")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result apiDeleteFlowRule(Long id) {

        if (id == null) {
            return Result.ofFail(-1, "id can't be null");
        }
        FlowRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofSuccess(null);
        }

        try {
            repository.delete(id);
        } catch (Exception e) {
            return Result.ofFail(-1, e.getMessage());
        }
        try {
            publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);
            return Result.ofSuccess(id);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Error when deleting flow rules, app={}, ip={}, id={}", oldEntity.getApp(),
                oldEntity.getIp(), id, e);
            return Result.ofFail(-1, e.getMessage());
        }
    }

    private CompletableFuture publishRules(String app, String ip, Integer port) {
        List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        // 修改前
//        return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
        // 修改后
        CompletableFuture async = sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
        try {
            if (null != rules) {
                flowRulePublisher.publish(app, rules);
            }
        } catch (Exception e) {
            logger.error("推送限流策略到Nacos失败, app={}, rule={}", app, rules, e);
        }
        return async;
    }
}

6. 熔断规则测试

  1. Nacos上先克隆备份一下原来配置
  2. Nacos上原来的配置
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图16
  3. Sentinel控制台
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图17
  4. 修改Sentinel控制台上修改
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图18
  5. 查看Nacos修改后的配置
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图19
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图20
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图21
  6. 接口设置睡眠100毫秒
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图22
  7. Jmeter压测
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图23
  8. 修改超时为90毫秒再测试
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图24
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图25
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图26
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图27
  9. 添加测试
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图28
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图29
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图30
  10. 删除测试
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图31
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图32
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图33

7. 限流规则测试

  1. Nacos上原来的配置
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图34
  2. Sentinel控制台
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图35
  3. 把接口之前设置100毫秒睡眠去掉
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图36
  4. 测试限流6个是否正常
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图37
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图38
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图39
  5. 修改Sentinel控制台上修改
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图40
  6. 查看Nacos修改后的配置
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图41
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图42
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图43
  7. Jmeter压测
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图44
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图45
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图46
  8. 添加测试
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图47
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图48
  9. 删除测试
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图49
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图50
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图51

8. 打包使用

  1. 打包只打控制台包就可以了
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图52
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图53
  2. 启动
    Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos插图54

文章来源于互联网:Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos

THE END
分享
二维码