网站建设要学习什么,wordpress 白屏,现在市场最火的网店平台,响应式酒店网站模板在网上找了很多的资料#xff0c;发现sentinel整合nacos持久化的博文和视频大多数都只有改造限流部分的教程#xff0c;并且都需要修改前端#xff0c;略显麻烦#xff0c;至于剩下的熔断、热点流控、授权的更是没有相关的改造教程#xff0c;最后在知乎的看到一篇文章后让…在网上找了很多的资料发现sentinel整合nacos持久化的博文和视频大多数都只有改造限流部分的教程并且都需要修改前端略显麻烦至于剩下的熔断、热点流控、授权的更是没有相关的改造教程最后在知乎的看到一篇文章后让我大受启发 这位前辈讲到sentinel原来是把配置保存到内存的我们只需要找出这行保存到内存的代码把它改为发布到nacos就可以了这样做改动非常的小而且不用改前端是个非常聪明的思路。
下面是我改造的过程完全不需要改前端
注释掉nacos依赖的test作用域
把test目录下nacos文件夹复制一份到java目录下
改造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 java.util.List;
import java.util.Properties;import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
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.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
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;/*** author Eric Zhao* since 1.4.0*/
Configuration
public class NacosConfig {// 动态配置nacos地址用户名密码Value(${sentinel.nacos.serverAddr})private String serverAddr;Value(${sentinel.nacos.username})private String username;Value(${sentinel.nacos.password})private String password;/*** 加入要改造方法所需实体的编解码器* return*/// 流控Beanpublic ConverterListFlowRuleEntity, String flowRuleEntityEncoder() {return JSON::toJSONString;}Beanpublic ConverterString, ListFlowRuleEntity flowRuleEntityDecoder() {return s - JSON.parseArray(s, FlowRuleEntity.class);}// 熔断Beanpublic ConverterListDegradeRuleEntity, String degradeRuleEntityEncoder() {return JSON::toJSONString;}Beanpublic ConverterString, ListDegradeRuleEntity degradeRuleEntityDecoder() {return s - JSON.parseArray(s, DegradeRuleEntity.class);}// 授权Beanpublic ConverterListAuthorityRuleEntity, String authorityRuleEntityEncoder() {return JSON::toJSONString;}Beanpublic ConverterString, ListAuthorityRuleEntity authorityRuleEntityDecoder() {return s - JSON.parseArray(s, AuthorityRuleEntity.class);}// 热点流控Beanpublic ConverterListParamFlowRuleEntity, String paramFlowRuleEntityEncoder() {return JSON::toJSONString;}Beanpublic ConverterString, ListParamFlowRuleEntity paramFlowRuleEntityDecoder() {return s - JSON.parseArray(s, ParamFlowRuleEntity.class);}Beanpublic ConfigService nacosConfigService() throws Exception {Properties properties new Properties();properties.put(serverAddr, serverAddr);properties.put(username, username);properties.put(password, password);return ConfigFactory.createConfigService(properties);
// return ConfigFactory.createConfigService(localhost);}
}
定义发布到配置中心的配置名后缀
/** 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;/*** 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 DEGRADE_DATA_ID_POSTFIX -degrade-rules;public static final String PARAM_FLOW_DATA_ID_POSTFIX -param-rules;public static final String AUTHORITY_DATA_ID_POSTFIX -authority-rules;public static final String CLUSTER_MAP_DATA_ID_POSTFIX -cluster-map;/*** 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() {}}配置文件中加入需要自定义的配置
#spring settings
server.servlet.encoding.forcetrue
server.servlet.encoding.charsetUTF-8
server.servlet.encoding.enabledtrue#cookie name setting
server.servlet.session.cookie.namesentinel_dashboard_cookie#logging settings
logging.level.org.springframework.webINFO
logging.file.name${user.home}/logs/csp/sentinel-dashboard.log
logging.pattern.file %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
#logging.pattern.console %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n#auth settings
auth.filter.exclude-urls/,/auth/login,/auth/logout,/registry/machine,/version
auth.filter.exclude-url-suffixeshtm,html,js,css,map,ico,ttf,woff,png
# If auth.enabledfalse, Sentinel console disable login
auth.usernamesentinel
auth.passwordsentinel# Inject the dashboard version. Its required to enable
# filtering in pom.xml for this resource file.
sentinel.dashboard.versionproject.versionsentinel.nacos.serverAddr 127.0.0.1:8848
sentinel.nacos.username nacos
sentinel.nacos.password nacos
sentinel.nacos.groupId SENTINEL_GROUP# custom dataId postfix
sentinel.custom.FLOW_DATA_ID_POSTFIX
sentinel.custom.DEGRADE_DATA_ID_POSTFIX
sentinel.custom.AUTHORITY_DATA_ID_POSTFIX
sentinel.custom.PARAM_FLOW_DATA_ID_POSTFIX FlowRuleNacosProvider 类改造
package com.alibaba.csp.sentinel.dashboard.rule.nacos;import java.util.ArrayList;
import java.util.List;
import java.util.Objects;import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** author Eric Zhao* since 1.4.0*/
Component(flowRuleNacosProvider)
public class FlowRuleNacosProvider implements DynamicRuleProviderListFlowRuleEntity {Autowiredprivate ConfigService configService;Autowiredprivate ConverterString, ListFlowRuleEntity converter;// 增加的代码Value(${sentinel.nacos.groupId})private String groupId;// 增加的代码Value(${sentinel.custom.FLOW_DATA_ID_POSTFIX})private String dataIdPostfix;Overridepublic ListFlowRuleEntity getRules(String appName) throws Exception {// 增加的代码 用于判断是否自定义dataid后缀if (dataIdPostfix.isEmpty()){dataIdPostfix NacosConfigUtil.FLOW_DATA_ID_POSTFIX;}String rules configService.getConfig(appName dataIdPostfix,groupId, 3000);if (StringUtil.isEmpty(rules)) {return new ArrayList();}return converter.convert(rules);}
}
FlowRuleNacosPublisher 类的改造
package com.alibaba.csp.sentinel.dashboard.rule.nacos;import java.util.List;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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** author Eric Zhao* since 1.4.0*/
Component(flowRuleNacosPublisher)
public class FlowRuleNacosPublisher implements DynamicRulePublisherListFlowRuleEntity {Autowiredprivate ConfigService configService;Autowiredprivate ConverterListFlowRuleEntity, String converter;// 增加的代码Value(${sentinel.nacos.groupId})private String groupId;// 增加的代码Value(${sentinel.custom.FLOW_DATA_ID_POSTFIX})private String dataIdPostfix;Overridepublic void publish(String app, ListFlowRuleEntity rules) throws Exception {// 增加的代码 用于判断是否自定义dataid后缀if (dataIdPostfix.isEmpty()){dataIdPostfix NacosConfigUtil.FLOW_DATA_ID_POSTFIX;}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));configService.publishConfig(app dataIdPostfix,groupId, converter.convert(rules));}
}
熔断、授权、热点流控Provider和Publisher的改造与流控的类似改下对应实体类型、后缀、组件名即可
FlowControllerV1 类的改造
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.discovery.AppManagement;
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.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);Autowiredprivate InMemoryRuleRepositoryAdapterFlowRuleEntity repository;Autowiredprivate AppManagement appManagement;Autowiredprivate SentinelApiClient sentinelApiClient;// 增加的代码注入用于发布nacos配置的类AutowiredQualifier(flowRuleNacosProvider)private DynamicRuleProviderListFlowRuleEntity ruleProvider;AutowiredQualifier(flowRuleNacosPublisher)private DynamicRulePublisherListFlowRuleEntity rulePublisher;GetMapping(/rules)AuthAction(PrivilegeType.READ_RULE)public ResultListFlowRuleEntity apiQueryMachineRules(RequestParam String app,RequestParam String ip,RequestParam Integer port) {if (StringUtil.isEmpty(app)) {return Result.ofFail(-1, app cant be null or empty);}if (StringUtil.isEmpty(ip)) {return Result.ofFail(-1, ip cant be null or empty);}if (port null) {return Result.ofFail(-1, port cant be null);}if (!appManagement.isValidMachineOfApp(app, ip)) {return Result.ofFail(-1, given ip does not belong to given app);}try {
// ListFlowRuleEntity rules sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);// 增加的代码把查询内存改为查询naocos配置中心ListFlowRuleEntity rules ruleProvider.getRules(app);if (rules ! null !rules.isEmpty()) {for (FlowRuleEntity entity : rules) {entity.setApp(app);if (entity.getClusterConfig() ! null entity.getClusterConfig().getFlowId() ! null) {entity.setId(entity.getClusterConfig().getFlowId());}}}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 CompletableFutureVoid publishRules(String app, String ip, Integer port) throws Exception {ListFlowRuleEntity rules repository.findAllByMachine(MachineInfo.of(app, ip, port));// 增加的代码把新增的规则发布到指定的nacos配置中心rulePublisher.publish(app, rules);// 保留保存到内存的逻辑return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);}
}
DegradeController 类改造
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.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
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.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);Autowiredprivate RuleRepositoryDegradeRuleEntity, Long repository;Autowiredprivate SentinelApiClient sentinelApiClient;// 增加的代码注入用于发布nacos配置的类AutowiredQualifier(degradeRuleNacosProvider)private DynamicRuleProviderListDegradeRuleEntity ruleProvider;AutowiredQualifier(degradeRuleNacosPublisher)private DynamicRulePublisherListDegradeRuleEntity rulePublisher;Autowiredprivate AppManagement appManagement;GetMapping(/rules.json)AuthAction(PrivilegeType.READ_RULE)public ResultListDegradeRuleEntity apiQueryMachineRules(String app, String ip, Integer port) {if (StringUtil.isEmpty(app)) {return Result.ofFail(-1, app cant be null or empty);}if (StringUtil.isEmpty(ip)) {return Result.ofFail(-1, ip cant be null or empty);}if (port null) {return Result.ofFail(-1, port cant be null);}if (!appManagement.isValidMachineOfApp(app, ip)) {return Result.ofFail(-1, given ip does not belong to given app);}try {// 增加的代码 查询nacos配置中心ListDegradeRuleEntity rules ruleProvider.getRules(app);if (rules ! null !rules.isEmpty()) {for (DegradeRuleEntity entity : rules) {entity.setApp(app);}}
// ListDegradeRuleEntity 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);}}....private boolean publishRules(String app, String ip, Integer port) throws Exception {ListDegradeRuleEntity rules repository.findAllByMachine(MachineInfo.of(app, ip, port));// 增加的代码 保存到nacosrulePublisher.publish(app, rules);return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);}
}
AuthorityRuleController 类的改造
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.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
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.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;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 /authority)
public class AuthorityRuleController {private final Logger logger LoggerFactory.getLogger(AuthorityRuleController.class);Autowiredprivate SentinelApiClient sentinelApiClient;Autowiredprivate RuleRepositoryAuthorityRuleEntity, Long repository;Autowiredprivate AppManagement appManagement;// 增加的代码注入用于发布nacos配置的类AutowiredQualifier(authorityRuleNacosProvider)private DynamicRuleProviderListAuthorityRuleEntity ruleProvider;AutowiredQualifier(authorityRuleNacosPublisher)private DynamicRulePublisherListAuthorityRuleEntity rulePublisher;GetMapping(/rules)AuthAction(PrivilegeType.READ_RULE)public ResultListAuthorityRuleEntity 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 (!appManagement.isValidMachineOfApp(app, ip)) {return Result.ofFail(-1, given ip does not belong to given app);}try {
// ListAuthorityRuleEntity rules sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port);// 增加的代码 查询nacos配置中心ListAuthorityRuleEntity rules ruleProvider.getRules(app);if (rules ! null !rules.isEmpty()) {for (AuthorityRuleEntity entity : rules) {entity.setApp(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 boolean publishRules(String app, String ip, Integer port) throws Exception {ListAuthorityRuleEntity rules repository.findAllByMachine(MachineInfo.of(app, ip, port));// 增加的代码 保存到nacosrulePublisher.publish(app, rules);return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules);}
}
ParamFlowRuleController 类的改造Provider查询类返回类型不同对应的Provider类也要做相应的修改
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 java.util.stream.Collectors;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.datasource.entity.rule.FlowRuleEntity;
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.dashboard.rule.nacos.ParamFlowRuleNacosProvider;
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);Autowiredprivate SentinelApiClient sentinelApiClient;Autowiredprivate AppManagement appManagement;Autowiredprivate RuleRepositoryParamFlowRuleEntity, Long repository;// 增加的代码注入用于发布nacos配置的类// 这个查询返回的类型与其他三个方法有些区别AutowiredQualifier(paramFlowRuleNacosProvider)private ParamFlowRuleNacosProvider ruleProvider;AutowiredQualifier(paramFlowRuleNacosPublisher)private DynamicRulePublisherListParamFlowRuleEntity rulePublisher;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 ResultListParamFlowRuleEntity 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 (!appManagement.isValidMachineOfApp(app, ip)) {return Result.ofFail(-1, given ip does not belong to given app);}if (!checkIfSupported(app, ip, port)) {return unsupportedVersion();}try {// 增加的代码 查询nacos配置中心 与其他三个方法有些区别return ruleProvider.getRules(app).thenApply(repository::saveAll).thenApply(Result::ofSuccess).get();
// return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port)
// .thenApply(repository::saveAll)
// .thenApply(Result::ofSuccess)
// .get();} 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;}...private CompletableFutureVoid publishRules(String app, String ip, Integer port) throws Exception {ListParamFlowRuleEntity rules repository.findAllByMachine(MachineInfo.of(app, ip, port));// 增加的代码 保存到nacosrulePublisher.publish(app, rules);return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);}
}
具体的ParamFlowRuleNacosProvider 类
package com.alibaba.csp.sentinel.dashboard.rule.nacos;import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.concurrent.CompletableFuture;/*** ClassName: ParamFlowRuleNacosProvider* Description: TODO* Author: ChiKin Lau SUSE* Date: 2023/11/8 10:08* version: 1.0**/
Component(paramFlowRuleNacosProvider)
public class ParamFlowRuleNacosProvider {Autowiredprivate ConfigService configService;Autowiredprivate ConverterString, ListParamFlowRuleEntity converter;// 增加的代码Value(${sentinel.nacos.groupId})private String groupId;Value(${sentinel.custom.PARAM_FLOW_DATA_ID_POSTFIX})private String dataIdPostfix;public CompletableFutureListParamFlowRuleEntity getRules(String appName) throws Exception {// 增加的代码 用于判断是否自定义dataid后缀if (dataIdPostfix.isEmpty()){dataIdPostfix NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX;}String rules configService.getConfig(appName dataIdPostfix,groupId, 3000);
// if (StringUtil.isEmpty(rules)) {
// return new CompletableFuture();
// }// 增加的代码 用于适应不同的返回类型CompletableFutureString future new CompletableFuture();future.complete(rules);return future.thenApply(json - JSON.parseArray(json, ParamFlowRuleEntity.class));}
}
OK至此所有的改造完成了使用maven进行打包即可使用使用这个jar包在页面端的sentinel配可以保存到nacos进行持久化了包括了流控、熔断、授权和热点限流。
下面附上 源码的GitHub地址 https://github.com/chikin-lau/sentinel-nacos jar包及使用说明压缩包 链接https://pan.baidu.com/s/1jvcSCQw-YjeT5-nRocQOUA 提取码8xry –来自百度网盘超级会员V3的分享 参考文章 https://zhuanlan.zhihu.com/p/663149010