一、下载sentinel源码
https://github.com/alibaba/Sentinel
二、Sentinel控制台改造(sentinel-dashboard)
1、修改pom.xml(sentinel-dashboard) 找到 如下依赖 把test注释掉
<!-- for Nacos rule publisher sample --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <!--<scope>test</scope>--> </dependency>
2、代码规则修改
1、修改之前参考一下官网的demo 路径如下:
sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
目录,将整个目录拷贝到
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
修改 NacosConfig 工具类
/* * 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.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.beans.factory.annotation.Value; 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 */ @Configuration public class NacosConfig { //本次新增 @Value("${nacos.address}") private String address; //本次新增 @Value("${nacos.namespace}") private String namespace; @Bean public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() { return JSON::toJSONString; } @Bean public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() { return s -> JSON.parseArray(s, FlowRuleEntity.class); } //本次注释 // @Bean // public ConfigService nacosConfigService() throws Exception { // return ConfigFactory.createConfigService("localhost"); // } //本次新增 @Bean public ConfigService nacosConfigService() throws Exception { Properties properties = new Properties(); //nacos集群地址 properties.put(PropertyKeyConst.SERVER_ADDR,address); //namespace为空即为public properties.put(PropertyKeyConst.NAMESPACE,namespace); return ConfigFactory.createConfigService(properties); } }
修改 application.properties 增加如下
nacos.address=192.168.1.X:8848 nacos.namespace=XXXXXXXXXXXX
在com.alibaba.csp.sentinel.dashboard.util添加一个JSONUtils 工具类
package com.alibaba.csp.sentinel.dashboard.util;/** * @program: sentinel-parent * @description: * @author: shiyanling * @create: 2021-01-15 13:14 **/ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @program: sentinel-parent * @description: * @author: shiyanling * @create: 2021-01-15 13:14 **/ public class JSONUtils { public static <T> String toJSONString(Object object) { try { return new ObjectMapper().writeValueAsString(object); } catch (JsonProcessingException e) { throw new IllegalArgumentException(e); } } public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) { return new ObjectMapper() .getTypeFactory() .constructParametricType(collectionClass, elementClasses); } public static <T> List<T> parseObject(Class<T> clazz, String string) { JavaType javaType = getCollectionType(ArrayList.class, clazz); try { return (List<T>) new ObjectMapper().readValue(string, javaType); } catch (IOException e) { throw new IllegalArgumentException(e); } } }View Code
NacosConfigUtil 文件修改(改动比较大 建议直接复制覆盖):
/* * 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.RuleEntity; import com.alibaba.csp.sentinel.dashboard.util.JSONUtils; import com.alibaba.csp.sentinel.slots.block.Rule; import com.alibaba.csp.sentinel.util.AssertUtil; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.exception.NacosException; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @author Eric Zhao * @since 1.4.0 */ public final class NacosConfigUtil { public static final String GROUP_ID = "SENTINEL_GROUP"; public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules"; public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules"; public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map"; public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules"; public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules"; public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules"; public static final String DASHBOARD_POSTFIX = "-dashboard"; /** * cc for `cluster-client` */ public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config"; /** * cs for `cluster-server` */ public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config"; public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config"; public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set"; private NacosConfigUtil() {} /** * 将规则序列化成JSON文本,存储到Nacos server中 * * @param configService nacos config service * @param app 应用名称 * @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX * @param rules 规则对象 * @throws NacosException 异常 */ public static <T> void setRuleStringToNacos(ConfigService configService, String app, String postfix, List<T> rules) throws NacosException { AssertUtil.notEmpty(app, "app name cannot be empty"); if (rules == null) { return; } List<Rule> ruleForApp = rules.stream() .map(rule -> { RuleEntity rule1 = (RuleEntity) rule; System.out.println(rule1.getClass()); Rule rule2 = rule1.toRule(); System.out.println(rule2.getClass()); return rule2; }) .collect(Collectors.toList()); // 存储,给微服务使用 String dataId = genDataId(app, postfix); configService.publishConfig( dataId, NacosConfigUtil.GROUP_ID, JSONUtils.toJSONString(ruleForApp) ); // 存储,给控制台使用 configService.publishConfig( dataId + DASHBOARD_POSTFIX, NacosConfigUtil.GROUP_ID, JSONUtils.toJSONString(rules) ); } /** * 从Nacos server中查询响应规则,并将其反序列化成对应Rule实体 * * @param configService nacos config service * @param appName 应用名称 * @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX * @param clazz 类 * @param <T> 泛型 * @return 规则对象列表 * @throws NacosException 异常 */ public static <T> List<T> getRuleEntitiesFromNacos(ConfigService configService, String appName, String postfix, Class<T> clazz) throws NacosException { String rules = configService.getConfig( genDataId(appName, postfix) + DASHBOARD_POSTFIX, NacosConfigUtil.GROUP_ID, 3000 ); if (StringUtil.isEmpty(rules)) { return new ArrayList<>(); } return JSONUtils.parseObject(clazz, rules); } private static String genDataId(String appName, String postfix) { return appName + postfix; } }View Code
公共部分目前修改完了 接下来是真正的规则设置修改
我们大概需要修改 五种规则设置 每种都需要修改 增加两个类文件 修改一个类文件分别是
FlowRuleNacosPublisher
FlowRuleNacosProvider
FlowControllerV1
【流控规则】 test工具类里面已经提供 我们直接修改即可
FlowRuleNacosPublisher .java
/* * 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.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; 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<List<FlowRuleEntity>> { @Autowired private ConfigService configService; //本次注释 // @Autowired // private Converter<List<FlowRuleEntity>, String> converter; @Override public void publish(String app, List<FlowRuleEntity> rules) throws Exception { //本次注释 // AssertUtil.notEmpty(app, "app name cannot be empty"); // if (rules == null) { // return; // } // configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, converter.convert(rules)); //本次新增 NacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.FLOW_DATA_ID_POSTFIX, rules ); } }View Code
FlowRuleNacosProvider .java
/* * 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.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @description 流控规则 * @author Eric Zhao * @since 1.4.0 */ @Component("flowRuleNacosProvider") public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> { @Autowired private ConfigService configService; //本次注释 // @Autowired // private Converter<String, List<FlowRuleEntity>> converter; @Override public List<FlowRuleEntity> getRules(String appName) throws Exception { //本次注释 // String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, 3000); // if (StringUtil.isEmpty(rules)) { // return new ArrayList<>(); // } // return converter.convert(rules); //本次新增 return NacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.FLOW_DATA_ID_POSTFIX, FlowRuleEntity.class ); } }View Code
FlowControllerV1.java
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.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; 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 com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; 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.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; import java.util.Date; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** * 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<FlowRuleEntity> repository; // 本次注释 // @Autowired // private SentinelApiClient sentinelApiClient; // 本次添加 开始 @Autowired @Qualifier("flowRuleNacosProvider") private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; @Autowired @Qualifier("flowRuleNacosPublisher") private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; // 本次添加 结束 @GetMapping("/rules") @AuthAction(PrivilegeType.READ_RULE) public Result<List<FlowRuleEntity>> 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<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port); //本次新增 List<FlowRuleEntity> rules = ruleProvider.getRules(app); 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 <R> Result<R> 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() < 0) { return Result.ofFail(-1, "count should be at lease zero"); } if (entity.getStrategy() == null) { return Result.ofFail(-1, "strategy can't be null"); } if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) { return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0"); } if (entity.getControlBehavior() == null) { return Result.ofFail(-1, "controlBehavior can't be null"); } int controlBehavior = entity.getControlBehavior(); if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) { return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1"); } if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) { return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2"); } if (entity.isClusterMode() && entity.getClusterConfig() == null) { return Result.ofFail(-1, "cluster config should be valid"); } return null; } @PostMapping("/rule") @AuthAction(PrivilegeType.WRITE_RULE) public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) { Result<FlowRuleEntity> 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()); //本次注释 // 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<FlowRuleEntity> 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()); //本次注释 // 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<Long> 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()); //本次注释 // 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<Void> publishRules(String app, String ip, Integer port) { // List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port)); // return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules); // } //本次新增 private void publishRules(/*@NonNull*/ String app) throws Exception { List<FlowRuleEntity> rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); } }View Code
【系统规则】
1、复制 FlowRuleNacosPublisher .java 重命名为 SystemRuleNacosPublisher 红的修改,绿色删除;
/* * 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.system; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; 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("systemRuleNacosPublisher") public class SystemRuleNacosPublisher implements DynamicRulePublisher<List<SystemRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<List<FlowRuleEntity>, String> converter; @Override public void publish(String app, List<SystemRuleEntity> rules) throws Exception { // AssertUtil.notEmpty(app, "app name cannot be empty"); // if (rules == null) { // return; // } // configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, converter.convert(rules)); NacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.SYSTEM_DATA_ID_POSTFIX, rules ); } }View Code
2、复制 FlowRuleNacosProvider .java 重命名为 SystemRuleNacosProvider 红的修改,绿色删除;
/* * 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.system; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @description 流控规则 * @author Eric Zhao * @since 1.4.0 */ @Component("systemRuleNacosProvider") public class SystemRuleNacosProvider implements DynamicRuleProvider<List<SystemRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<String, List<FlowRuleEntity>> converter; @Override public List<SystemRuleEntity> getRules(String appName) throws Exception { // String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, 3000); // if (StringUtil.isEmpty(rules)) { // return new ArrayList<>(); // } // return converter.convert(rules); return NacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.SYSTEM_DATA_ID_POSTFIX, SystemRuleEntity.class ); } }View Code
3、 修改: SystemController
/* * 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 com.alibaba.csp.sentinel.dashboard.auth.AuthAction; import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; import com.alibaba.csp.sentinel.dashboard.domain.Result; 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.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author leyou(lihao) */ @RestController @RequestMapping("/system") public class SystemController { private final Logger logger = LoggerFactory.getLogger(SystemController.class); @Autowired private RuleRepository<SystemRuleEntity, Long> repository; @Autowired @Qualifier("systemRuleNacosProvider") private DynamicRuleProvider<List<SystemRuleEntity>> ruleProvider; @Autowired @Qualifier("systemRuleNacosPublisher") private DynamicRulePublisher<List<SystemRuleEntity>> rulePublisher; private <R> Result<R> checkBasicParams(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"); } if (port <= 0 || port > 65535) { return Result.ofFail(-1, "port should be in (0, 65535)"); } return null; } @GetMapping("/rules.json") @AuthAction(PrivilegeType.READ_RULE) public Result<List<SystemRuleEntity>> apiQueryMachineRules(String app, String ip, Integer port) { Result<List<SystemRuleEntity>> checkResult = checkBasicParams(app, ip, port); if (checkResult != null) { return checkResult; } try { // List<SystemRuleEntity> rules = sentinelApiClient.fetchSystemRuleOfMachine(app, ip, port); List<SystemRuleEntity> rules = ruleProvider.getRules(app); rules = repository.saveAll(rules); return Result.ofSuccess(rules); } catch (Throwable throwable) { logger.error("Query machine system rules error", throwable); return Result.ofThrowable(-1, throwable); } } private int countNotNullAndNotNegative(Number... values) { int notNullCount = 0; for (int i = 0; i < values.length; i++) { if (values[i] != null && values[i].doubleValue() >= 0) { notNullCount++; } } return notNullCount; } @RequestMapping("/new.json") @AuthAction(PrivilegeType.WRITE_RULE) public Result<SystemRuleEntity> apiAdd(String app, String ip, Integer port, Double highestSystemLoad, Double highestCpuUsage, Long avgRt, Long maxThread, Double qps) { Result<SystemRuleEntity> checkResult = checkBasicParams(app, ip, port); if (checkResult != null) { return checkResult; } int notNullCount = countNotNullAndNotNegative(highestSystemLoad, avgRt, maxThread, qps, highestCpuUsage); if (notNullCount != 1) { return Result.ofFail(-1, "only one of [highestSystemLoad, avgRt, maxThread, qps,highestCpuUsage] " + "value must be set > 0, but " + notNullCount + " values get"); } if (null != highestCpuUsage && highestCpuUsage > 1) { return Result.ofFail(-1, "highestCpuUsage must between [0.0, 1.0]"); } SystemRuleEntity entity = new SystemRuleEntity(); entity.setApp(app.trim()); entity.setIp(ip.trim()); entity.setPort(port); // -1 is a fake value if (null != highestSystemLoad) { entity.setHighestSystemLoad(highestSystemLoad); } else { entity.setHighestSystemLoad(-1D); } if (null != highestCpuUsage) { entity.setHighestCpuUsage(highestCpuUsage); } else { entity.setHighestCpuUsage(-1D); } if (avgRt != null) { entity.setAvgRt(avgRt); } else { entity.setAvgRt(-1L); } if (maxThread != null) { entity.setMaxThread(maxThread); } else { entity.setMaxThread(-1L); } if (qps != null) { entity.setQps(qps); } else { entity.setQps(-1D); } Date date = new Date(); entity.setGmtCreate(date); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("Add SystemRule error", throwable); return Result.ofThrowable(-1, throwable); } // if (!publishRules(app, ip, port)) { // logger.warn("Publish system rules fail after rule add"); // } return Result.ofSuccess(entity); } @GetMapping("/save.json") @AuthAction(PrivilegeType.WRITE_RULE) public Result<SystemRuleEntity> apiUpdateIfNotNull(Long id, String app, Double highestSystemLoad, Double highestCpuUsage, Long avgRt, Long maxThread, Double qps) { if (id == null) { return Result.ofFail(-1, "id can't be null"); } SystemRuleEntity 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 (highestSystemLoad != null) { if (highestSystemLoad < 0) { return Result.ofFail(-1, "highestSystemLoad must >= 0"); } entity.setHighestSystemLoad(highestSystemLoad); } if (highestCpuUsage != null) { if (highestCpuUsage < 0) { return Result.ofFail(-1, "highestCpuUsage must >= 0"); } if (highestCpuUsage > 1) { return Result.ofFail(-1, "highestCpuUsage must <= 1"); } entity.setHighestCpuUsage(highestCpuUsage); } if (avgRt != null) { if (avgRt < 0) { return Result.ofFail(-1, "avgRt must >= 0"); } entity.setAvgRt(avgRt); } if (maxThread != null) { if (maxThread < 0) { return Result.ofFail(-1, "maxThread must >= 0"); } entity.setMaxThread(maxThread); } if (qps != null) { if (qps < 0) { return Result.ofFail(-1, "qps must >= 0"); } entity.setQps(qps); } Date date = new Date(); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("save error:", throwable); return Result.ofThrowable(-1, throwable); } // if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) { // logger.info("publish system rules fail after rule update"); // } return Result.ofSuccess(entity); } @RequestMapping("/delete.json") @AuthAction(PrivilegeType.DELETE_RULE) public Result<?> delete(Long id) { if (id == null) { return Result.ofFail(-1, "id can't be null"); } SystemRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofSuccess(null); } try { repository.delete(id); publishRules(oldEntity.getApp()); } catch (Throwable throwable) { logger.error("delete error:", throwable); return Result.ofThrowable(-1, throwable); } // if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) { // logger.info("publish system rules fail after rule delete"); // } return Result.ofSuccess(id); } // private boolean publishRules(String app, String ip, Integer port) { // List<SystemRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port)); // return sentinelApiClient.setSystemRuleOfMachine(app, ip, port, rules); // } private void publishRules(String app) throws Exception { List<SystemRuleEntity> rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); } }View Code
剩余规则依次类推 下面我只提供类名与代码 方便大家使用
【授权规则】
/* * 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.authority; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @description 流控规则 * @author Eric Zhao * @since 1.4.0 */ @Component("authorityRuleNacosProvider") public class AuthorityRuleNacosProvider implements DynamicRuleProvider<List<AuthorityRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<String, List<FlowRuleEntity>> converter; @Override public List<AuthorityRuleEntity> getRules(String appName) throws Exception { // String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, 3000); // if (StringUtil.isEmpty(rules)) { // return new ArrayList<>(); // } // return converter.convert(rules); return NacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.AUTHORITY_DATA_ID_POSTFIX, AuthorityRuleEntity.class ); } }View Code
/* * 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.authority; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; 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("authorityRuleNacosPublisher") public class AuthorityRuleNacosPublisher implements DynamicRulePublisher<List<AuthorityRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<List<FlowRuleEntity>, String> converter; @Override public void publish(String app, List<AuthorityRuleEntity> rules) throws Exception { // AssertUtil.notEmpty(app, "app name cannot be empty"); // if (rules == null) { // return; // } // configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, converter.convert(rules)); NacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.AUTHORITY_DATA_ID_POSTFIX, rules ); } }View Code
/* * 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.datasource.entity.rule.AuthorityRuleEntity; 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.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.slots.block.RuleConstant; 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.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; 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; import java.util.Date; import java.util.List; /** * @author Eric Zhao * @since 0.2.1 */ @RestController @RequestMapping(value = "/authority") public class AuthorityRuleController { private final Logger logger = LoggerFactory.getLogger(AuthorityRuleController.class); // @Autowired // private SentinelApiClient sentinelApiClient; @Autowired @Qualifier("authorityRuleNacosProvider") private DynamicRuleProvider<List<AuthorityRuleEntity>> ruleProvider; @Autowired @Qualifier("authorityRuleNacosPublisher") private DynamicRulePublisher<List<AuthorityRuleEntity>> rulePublisher; @Autowired private RuleRepository<AuthorityRuleEntity, Long> repository; @GetMapping("/rules") @AuthAction(PrivilegeType.READ_RULE) public Result<List<AuthorityRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, @RequestParam String ip, @RequestParam Integer port) { if (StringUtil.isEmpty(app)) { return Result.ofFail(-1, "app cannot be null or empty"); } if (StringUtil.isEmpty(ip)) { return Result.ofFail(-1, "ip cannot be null or empty"); } if (port == null || port <= 0) { return Result.ofFail(-1, "Invalid parameter: port"); } try { // List<AuthorityRuleEntity> rules = sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port); List<AuthorityRuleEntity> rules = ruleProvider.getRules(app); rules = repository.saveAll(rules); return Result.ofSuccess(rules); } catch (Throwable throwable) { logger.error("Error when querying authority rules", throwable); return Result.ofFail(-1, throwable.getMessage()); } } private <R> Result<R> checkEntityInternal(AuthorityRuleEntity entity) { if (entity == null) { return Result.ofFail(-1, "bad rule body"); } 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 || entity.getPort() <= 0) { return Result.ofFail(-1, "port can't be null"); } if (entity.getRule() == null) { return Result.ofFail(-1, "rule can't be null"); } if (StringUtil.isBlank(entity.getResource())) { return Result.ofFail(-1, "resource name cannot be null or empty"); } if (StringUtil.isBlank(entity.getLimitApp())) { return Result.ofFail(-1, "limitApp should be valid"); } if (entity.getStrategy() != RuleConstant.AUTHORITY_WHITE && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) { return Result.ofFail(-1, "Unknown strategy (must be blacklist or whitelist)"); } return null; } @PostMapping("/rule") @AuthAction(PrivilegeType.WRITE_RULE) public Result<AuthorityRuleEntity> apiAddAuthorityRule(@RequestBody AuthorityRuleEntity entity) { Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } entity.setId(null); Date date = new Date(); entity.setGmtCreate(date); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("Failed to add authority rule", throwable); return Result.ofThrowable(-1, throwable); } // if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) { // logger.info("Publish authority rules failed after rule add"); // } return Result.ofSuccess(entity); } @PutMapping("/rule/{id}") @AuthAction(PrivilegeType.WRITE_RULE) public Result<AuthorityRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, @RequestBody AuthorityRuleEntity entity) { if (id == null || id <= 0) { return Result.ofFail(-1, "Invalid id"); } Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } entity.setId(id); Date date = new Date(); entity.setGmtCreate(null); entity.setGmtModified(date); try { entity = repository.save(entity); if (entity == null) { return Result.ofFail(-1, "Failed to save authority rule"); } publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("Failed to save authority rule", throwable); return Result.ofThrowable(-1, throwable); } // if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) { // logger.info("Publish authority rules failed after rule update"); // } return Result.ofSuccess(entity); } @DeleteMapping("/rule/{id}") @AuthAction(PrivilegeType.DELETE_RULE) public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { if (id == null) { return Result.ofFail(-1, "id cannot be null"); } AuthorityRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofSuccess(null); } try { repository.delete(id); publishRules(oldEntity.getApp()); } catch (Exception e) { return Result.ofFail(-1, e.getMessage()); } // if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) { // logger.error("Publish authority rules failed after rule delete"); // } return Result.ofSuccess(id); } // private boolean publishRules(String app, String ip, Integer port) { // List<AuthorityRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port)); // return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules); // } private void publishRules(String app) throws Exception { List<AuthorityRuleEntity> rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); } }View Code
【热点规则】
/* * 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.param; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @description 流控规则 * @author Eric Zhao * @since 1.4.0 */ @Component("paramFlowRuleNacosProvider") public class ParamFlowRuleNacosProvider implements DynamicRuleProvider<List<ParamFlowRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<String, List<FlowRuleEntity>> converter; @Override public List<ParamFlowRuleEntity> getRules(String appName) throws Exception { // String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, 3000); // if (StringUtil.isEmpty(rules)) { // return new ArrayList<>(); // } // return converter.convert(rules); return NacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX, ParamFlowRuleEntity.class ); } }View Code
/* * 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.param; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; 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("paramFlowRuleNacosPublisher") public class ParamFlowRuleNacosPublisher implements DynamicRulePublisher<List<ParamFlowRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<List<FlowRuleEntity>, String> converter; @Override public void publish(String app, List<ParamFlowRuleEntity> rules) throws Exception { NacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX, rules ); } }View Code
/* * 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.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException; import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement; import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; import com.alibaba.csp.sentinel.dashboard.auth.AuthService; import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.domain.Result; import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; import com.alibaba.csp.sentinel.dashboard.util.VersionUtils; 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.PathVariable; 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; /** * @author Eric Zhao * @since 0.2.1 */ @RestController @RequestMapping(value = "/paramFlow") public class ParamFlowRuleController { private final Logger logger = LoggerFactory.getLogger(ParamFlowRuleController.class); // // @Autowired // private SentinelApiClient sentinelApiClient; @Autowired @Qualifier("paramFlowRuleNacosProvider") private DynamicRuleProvider<List<ParamFlowRuleEntity>> ruleProvider; @Autowired @Qualifier("paramFlowRuleNacosPublisher") private DynamicRulePublisher<List<ParamFlowRuleEntity>> rulePublisher; @Autowired private AppManagement appManagement; @Autowired private RuleRepository<ParamFlowRuleEntity, Long> repository; private boolean checkIfSupported(String app, String ip, int port) { try { return Optional.ofNullable(appManagement.getDetailApp(app)) .flatMap(e -> e.getMachine(ip, port)) .flatMap(m -> VersionUtils.parseVersion(m.getVersion()) .map(v -> v.greaterOrEqual(version020))) .orElse(true); // If error occurred or cannot retrieve machine info, return true. } catch (Exception ex) { return true; } } @GetMapping("/rules") @AuthAction(PrivilegeType.READ_RULE) public Result<List<ParamFlowRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, @RequestParam String ip, @RequestParam Integer port) { if (StringUtil.isEmpty(app)) { return Result.ofFail(-1, "app cannot be null or empty"); } if (StringUtil.isEmpty(ip)) { return Result.ofFail(-1, "ip cannot be null or empty"); } if (port == null || port <= 0) { return Result.ofFail(-1, "Invalid parameter: port"); } if (!checkIfSupported(app, ip, port)) { return unsupportedVersion(); } try { // return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port) // .thenApply(repository::saveAll) // .thenApply(Result::ofSuccess) // .get(); List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app); rules = repository.saveAll(rules); return Result.ofSuccess(rules); } catch (ExecutionException ex) { logger.error("Error when querying parameter flow rules", ex.getCause()); if (isNotSupported(ex.getCause())) { return unsupportedVersion(); } else { return Result.ofThrowable(-1, ex.getCause()); } } catch (Throwable throwable) { logger.error("Error when querying parameter flow rules", throwable); return Result.ofFail(-1, throwable.getMessage()); } } private boolean isNotSupported(Throwable ex) { return ex instanceof CommandNotFoundException; } @PostMapping("/rule") @AuthAction(AuthService.PrivilegeType.WRITE_RULE) public Result<ParamFlowRuleEntity> apiAddParamFlowRule(@RequestBody ParamFlowRuleEntity entity) { Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) { return unsupportedVersion(); } entity.setId(null); entity.getRule().setResource(entity.getResource().trim()); Date date = new Date(); entity.setGmtCreate(date); entity.setGmtModified(date); try { entity = repository.save(entity); // publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(); publishRules(entity.getApp()); return Result.ofSuccess(entity); } catch (ExecutionException ex) { logger.error("Error when adding new parameter flow rules", ex.getCause()); if (isNotSupported(ex.getCause())) { return unsupportedVersion(); } else { return Result.ofThrowable(-1, ex.getCause()); } } catch (Throwable throwable) { logger.error("Error when adding new parameter flow rules", throwable); return Result.ofFail(-1, throwable.getMessage()); } } private <R> Result<R> checkEntityInternal(ParamFlowRuleEntity entity) { if (entity == null) { return Result.ofFail(-1, "bad rule body"); } 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 || entity.getPort() <= 0) { return Result.ofFail(-1, "port can't be null"); } if (entity.getRule() == null) { return Result.ofFail(-1, "rule can't be null"); } if (StringUtil.isBlank(entity.getResource())) { return Result.ofFail(-1, "resource name cannot be null or empty"); } if (entity.getCount() < 0) { return Result.ofFail(-1, "count should be valid"); } if (entity.getGrade() != RuleConstant.FLOW_GRADE_QPS) { return Result.ofFail(-1, "Unknown mode (blockGrade) for parameter flow control"); } if (entity.getParamIdx() == null || entity.getParamIdx() < 0) { return Result.ofFail(-1, "paramIdx should be valid"); } if (entity.getDurationInSec() <= 0) { return Result.ofFail(-1, "durationInSec should be valid"); } if (entity.getControlBehavior() < 0) { return Result.ofFail(-1, "controlBehavior should be valid"); } return null; } @PutMapping("/rule/{id}") @AuthAction(AuthService.PrivilegeType.WRITE_RULE) public Result<ParamFlowRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, @RequestBody ParamFlowRuleEntity entity) { if (id == null || id <= 0) { return Result.ofFail(-1, "Invalid id"); } ParamFlowRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofFail(-1, "id " + id + " does not exist"); } Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) { return unsupportedVersion(); } entity.setId(id); Date date = new Date(); entity.setGmtCreate(oldEntity.getGmtCreate()); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); // publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(); return Result.ofSuccess(entity); } catch (ExecutionException ex) { logger.error("Error when updating parameter flow rules, id=" + id, ex.getCause()); if (isNotSupported(ex.getCause())) { return unsupportedVersion(); } else { return Result.ofThrowable(-1, ex.getCause()); } } catch (Throwable throwable) { logger.error("Error when updating parameter flow rules, id=" + id, throwable); return Result.ofFail(-1, throwable.getMessage()); } } @DeleteMapping("/rule/{id}") @AuthAction(PrivilegeType.DELETE_RULE) public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { if (id == null) { return Result.ofFail(-1, "id cannot be null"); } ParamFlowRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofSuccess(null); } try { repository.delete(id); publishRules(oldEntity.getApp()); // publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(); return Result.ofSuccess(id); } catch (ExecutionException ex) { logger.error("Error when deleting parameter flow rules", ex.getCause()); if (isNotSupported(ex.getCause())) { return unsupportedVersion(); } else { return Result.ofThrowable(-1, ex.getCause()); } } catch (Throwable throwable) { logger.error("Error when deleting parameter flow rules", throwable); return Result.ofFail(-1, throwable.getMessage()); } } // private CompletableFuture<Void> publishRules(String app, String ip, Integer port) { // List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port)); // return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules); // } private void publishRules(String app) throws Exception { List<ParamFlowRuleEntity> rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); } private <R> Result<R> unsupportedVersion() { return Result.ofFail(4041, "Sentinel client not supported for parameter flow control (unsupported version or dependency absent)"); } private final SentinelVersion version020 = new SentinelVersion().setMinorVersion(2); }View Code
【降级规则】
/* * 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.degrade; 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.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil; import com.alibaba.nacos.api.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; /** * @description 流控规则 * @author Eric Zhao * @since 1.4.0 */ @Component("degradeRuleNacosProvider") public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<String, List<FlowRuleEntity>> converter; @Override public List<DegradeRuleEntity> getRules(String appName) throws Exception { // String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, 3000); // if (StringUtil.isEmpty(rules)) { // return new ArrayList<>(); // } // return converter.convert(rules); return NacosConfigUtil.getRuleEntitiesFromNacos( this.configService, appName, NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX, DegradeRuleEntity.class ); } }View Code
/* * 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.degrade; 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.dashboard.rule.nacos.NacosConfigUtil; 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<List<DegradeRuleEntity>> { @Autowired private ConfigService configService; // @Autowired // private Converter<List<FlowRuleEntity>, String> converter; @Override public void publish(String app, List<DegradeRuleEntity> rules) throws Exception { // AssertUtil.notEmpty(app, "app name cannot be empty"); // if (rules == null) { // return; // } // configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, // NacosConfigUtil.GROUP_ID, converter.convert(rules)); NacosConfigUtil.setRuleStringToNacos( this.configService, app, NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX, rules ); } }View Code
/* * 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 com.alibaba.csp.sentinel.dashboard.auth.AuthAction; import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; 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 com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; import com.alibaba.csp.sentinel.dashboard.domain.Result; 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.PathVariable; 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.RestController; /** * 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<DegradeRuleEntity, Long> repository; // @Autowired // private SentinelApiClient sentinelApiClient; @Autowired @Qualifier("degradeRuleNacosProvider") private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider; @Autowired @Qualifier("degradeRuleNacosPublisher") private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher; @GetMapping("/rules.json") @AuthAction(PrivilegeType.READ_RULE) public Result<List<DegradeRuleEntity>> 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<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port); List<DegradeRuleEntity> rules = ruleProvider.getRules(app); 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<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) { Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } Date date = new Date(); entity.setGmtCreate(date); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); } 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<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id, @RequestBody DegradeRuleEntity entity) { if (id == null || id <= 0) { return Result.ofFail(-1, "id can't be null or negative"); } DegradeRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofFail(-1, "Degrade rule does not exist, id=" + id); } entity.setApp(oldEntity.getApp()); entity.setIp(oldEntity.getIp()); entity.setPort(oldEntity.getPort()); entity.setId(oldEntity.getId()); Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } entity.setGmtCreate(oldEntity.getGmtCreate()); entity.setGmtModified(new Date()); try { entity = repository.save(entity); publishRules(entity.getApp()); } 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<Long> 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); publishRules(oldEntity.getApp()); } 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<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port)); // return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules); // } private void publishRules(String app) throws Exception { List<DegradeRuleEntity> rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); } private <R> Result<R> 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() <= 0) { return Result.ofFail(-1, "invalid port: " + entity.getPort()); } 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"); } Double threshold = entity.getCount(); if (threshold == null || threshold < 0) { return Result.ofFail(-1, "invalid threshold: " + threshold); } Integer recoveryTimeoutSec = entity.getTimeWindow(); if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) { return Result.ofFail(-1, "recoveryTimeout should be positive"); } Integer strategy = entity.getGrade(); if (strategy == null) { return Result.ofFail(-1, "circuit breaker strategy cannot be null"); } if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType() || strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) { return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy); } if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount() <= 0) { return Result.ofFail(-1, "Invalid minRequestAmount"); } if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) { return Result.ofFail(-1, "Invalid statInterval"); } if (strategy == RuleConstant.DEGRADE_GRADE_RT) { Double slowRatio = entity.getSlowRatioThreshold(); if (slowRatio == null) { return Result.ofFail(-1, "SlowRatioThreshold is required for slow request ratio strategy"); } else if (slowRatio < 0 || slowRatio > 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; } }View Code
至此 所有的改造 完成 仅供自己学习参考 暂时未使用在生产环境~如有错误 欢迎指正!!!
参考博客 :https://blog.csdn.net/qq_38723394/article/details/108991518