当前位置:   article > 正文

Sentinel持久化到nacos 举例流控和熔断规则_sentinel-datasource-nacos

sentinel-datasource-nacos

环境准备:
Nacos2.2.0集群搭建
版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

安装,配置nacos不多说

1.下载Sentinel源代码

地址:Sentinel1.8.6:https://github.com/alibaba/Sentinel/releases/tag/1.8.6

解压后使用IDEA打开sentinel-dashboard

 2.修改代码

1.修改pom.xml

104行注释掉: test

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <!--<scope>test</scope>-->
</dependency>

 2.复制一份test中的nacos到rule中

复制:

 放入:

 3.新建 NacosConfigProperties.java 文件

  1. package com.alibaba.csp.sentinel.dashboard.rule.nacos;
  2. import org.springframework.boot.context.properties.ConfigurationProperties;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. @ConfigurationProperties(prefix = "sentinel.nacos")
  6. public class NacosConfigProperties {
  7. // nacos地址
  8. private String serverAddr;
  9. // nacos登录名
  10. private String username;
  11. // nacos 登录密码
  12. private String password;
  13. // nacos命名空间
  14. private String namespace;
  15. public String getServerAddr() {
  16. return serverAddr;
  17. }
  18. public void setServerAddr(String serverAddr) {
  19. this.serverAddr = serverAddr;
  20. }
  21. public String getUsername() {
  22. return username;
  23. }
  24. public void setUsername(String username) {
  25. this.username = username;
  26. }
  27. public String getPassword() {
  28. return password;
  29. }
  30. public void setPassword(String password) {
  31. this.password = password;
  32. }
  33. public String getNamespace() {
  34. return namespace;
  35. }
  36. public void setNamespace(String namespace) {
  37. this.namespace = namespace;
  38. }
  39. }

4.修改NacosConfig.java文件

  1. /*
  2. * Copyright 1999-2018 Alibaba Group Holding Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.csp.sentinel.dashboard.rule.nacos;
  17. import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
  18. import com.alibaba.csp.sentinel.datasource.Converter;
  19. import com.alibaba.fastjson.JSON;
  20. import com.alibaba.nacos.api.PropertyKeyConst;
  21. import com.alibaba.nacos.api.config.ConfigFactory;
  22. import com.alibaba.nacos.api.config.ConfigService;
  23. import org.springframework.beans.factory.annotation.Autowired;
  24. import org.springframework.context.annotation.Bean;
  25. import org.springframework.context.annotation.Configuration;
  26. import java.util.List;
  27. import java.util.Properties;
  28. /**
  29. * @author Eric Zhao
  30. * @since 1.4.0
  31. */
  32. @Configuration
  33. public class NacosConfig {
  34. // 注入刚新建的nacos配置文件
  35. @Autowired
  36. private NacosConfigProperties nacosConfigProperties;
  37. @Bean
  38. public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
  39. return JSON::toJSONString;
  40. }
  41. @Bean
  42. public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
  43. return s -> JSON.parseArray(s, FlowRuleEntity.class);
  44. }
  45. @Bean
  46. public ConfigService nacosConfigService() throws Exception {
  47. // 注释
  48. // return ConfigFactory.createConfigService("localhost");
  49. // 新增
  50. Properties properties = new Properties();
  51. properties.put(PropertyKeyConst.SERVER_ADDR,nacosConfigProperties.getServerAddr());
  52. properties.put(PropertyKeyConst.USERNAME,nacosConfigProperties.getUsername());
  53. properties.put(PropertyKeyConst.PASSWORD,nacosConfigProperties.getPassword());
  54. properties.put(PropertyKeyConst.NAMESPACE,nacosConfigProperties.getNamespace());
  55. return ConfigFactory.createConfigService(properties);
  56. }
  57. }

5.修改FlowControllerV2,将注解换成我们定义的类

 6.修改前端代码:修改sidebar.html

修改resources/app/scripts/directives/sidebar/sidebar.html
直接搜dashboard.flowV1定位57行去掉V1

 7.修改js:修改identity.js

// 'FlowServiceV1' 替换为 'FlowServiceV2'

 8.直接搜/dashboard/flow/定位第101行

let url = '/dashboard/flow/' + $scope.app; 替换为:let url = '/dashboard/v2/flow/' + $scope.app;

 9.项目application.properties 新增配置

  1. # 服务端口、控制台地址、名称
  2. server.port=9100
  3. csp.sentinel.dashboard.server=127.0.0.1:9100
  4. project.name=sentinel-dashboard
  5. # Nacos地址、账号、密码
  6. sentinel.nacos.serverAddr=192.168.20.128:8999
  7. sentinel.nacos.username=nacos
  8. sentinel.nacos.password=nacos
  9. # 默认命名空间就是 public,不用填写,填了public反而找不到,所以这个置空就行。
  10. sentinel.nacos.namespace=

效果:

10.熔断改造,前面跟着走的可以直接复制代码

第一步:

在【com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade】包下增加【DegradeRuleNacosProvider】类

  1. /*
  2. * Copyright 1999-2018 Alibaba Group Holding Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.csp.sentinel.dashboard.rule.nacos;
  17. import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
  18. import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
  19. import com.alibaba.csp.sentinel.datasource.Converter;
  20. import com.alibaba.csp.sentinel.util.StringUtil;
  21. import com.alibaba.nacos.api.config.ConfigService;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.stereotype.Component;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. /**
  27. * @author Eric Zhao
  28. * @since 1.4.0
  29. */
  30. @Component("flowRuleNacosProvider")
  31. public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
  32. @Autowired
  33. private ConfigService configService;
  34. @Autowired
  35. private Converter<String, List<FlowRuleEntity>> converter;
  36. @Override
  37. public List<FlowRuleEntity> getRules(String appName) throws Exception {
  38. String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
  39. NacosConfigUtil.GROUP_ID, 3000);
  40. if (StringUtil.isEmpty(rules)) {
  41. return new ArrayList<>();
  42. }
  43. return converter.convert(rules);
  44. }
  45. }

第二步:在【com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade】包下增加【DegradeRuleNacosPublisher】类

  1. /**
  2. * @author Eric Zhao
  3. * @since 1.4.0
  4. */
  5. @Component("flowRuleNacosPublisher")
  6. public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
  7. @Autowired
  8. private ConfigService configService;
  9. @Autowired
  10. private Converter<List<FlowRuleEntity>, String> converter;
  11. @Override
  12. public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
  13. AssertUtil.notEmpty(app, "app name cannot be empty");
  14. if (rules == null) {
  15. return;
  16. }
  17. configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
  18. NacosConfigUtil.GROUP_ID, converter.convert(rules));
  19. }
  20. }

第三步:改造

  1. /*
  2. * Copyright 1999-2018 Alibaba Group Holding Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.csp.sentinel.dashboard.controller;
  17. import java.util.Date;
  18. import java.util.List;
  19. import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
  20. import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
  21. import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
  22. import com.alibaba.csp.sentinel.dashboard.controller.v2.DegradeControllerV1;
  23. import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
  24. import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
  25. import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
  26. import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
  27. import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
  28. import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
  29. import com.alibaba.csp.sentinel.slots.block.RuleConstant;
  30. import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
  31. import com.alibaba.csp.sentinel.util.StringUtil;
  32. import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
  33. import com.alibaba.csp.sentinel.dashboard.domain.Result;
  34. import org.slf4j.Logger;
  35. import org.slf4j.LoggerFactory;
  36. import org.springframework.beans.factory.annotation.Autowired;
  37. import org.springframework.beans.factory.annotation.Qualifier;
  38. import org.springframework.web.bind.annotation.DeleteMapping;
  39. import org.springframework.web.bind.annotation.GetMapping;
  40. import org.springframework.web.bind.annotation.PathVariable;
  41. import org.springframework.web.bind.annotation.PostMapping;
  42. import org.springframework.web.bind.annotation.PutMapping;
  43. import org.springframework.web.bind.annotation.RequestBody;
  44. import org.springframework.web.bind.annotation.RequestMapping;
  45. import org.springframework.web.bind.annotation.RestController;
  46. import javax.servlet.http.HttpServletRequest;
  47. /**
  48. * Controller regarding APIs of degrade rules. Refactored since 1.8.0.
  49. *
  50. * @author Carpenter Lee
  51. * @author Eric Zhao
  52. */
  53. @RestController
  54. @RequestMapping("/degrade")
  55. public class DegradeController {
  56. private final Logger logger = LoggerFactory.getLogger(DegradeController.class);
  57. @Autowired
  58. private RuleRepository<DegradeRuleEntity, Long> repository;
  59. @Autowired
  60. private AuthService<HttpServletRequest> authService;
  61. @Autowired
  62. @Qualifier("degradeRuleNacosProvider")
  63. private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;
  64. @Autowired
  65. @Qualifier("degradeRuleNacosPublisher")
  66. private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;
  67. @Autowired
  68. private SentinelApiClient sentinelApiClient;
  69. @GetMapping("/rules.json")
  70. @AuthAction(PrivilegeType.READ_RULE)
  71. public Result<List<DegradeRuleEntity>> apiQueryMachineRules(HttpServletRequest request, String app, String ip, Integer port) {
  72. AuthService.AuthUser authUser = authService.getAuthUser(request);
  73. authUser.authTarget(app, PrivilegeType.READ_RULE);
  74. if (StringUtil.isEmpty(app)) {
  75. return Result.ofFail(-1, "app can't be null or empty");
  76. }
  77. if (StringUtil.isEmpty(ip)) {
  78. return Result.ofFail(-1, "ip can't be null or empty");
  79. }
  80. if (port == null) {
  81. return Result.ofFail(-1, "port can't be null");
  82. }
  83. try {
  84. List<DegradeRuleEntity> rules = ruleProvider.getRules(app);
  85. rules = repository.saveAll(rules);
  86. return Result.ofSuccess(rules);
  87. } catch (Throwable throwable) {
  88. logger.error("queryApps error:", throwable);
  89. return Result.ofThrowable(-1, throwable);
  90. }
  91. }
  92. @PostMapping("/rule")
  93. @AuthAction(PrivilegeType.WRITE_RULE)
  94. public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) {
  95. Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
  96. if (checkResult != null) {
  97. return checkResult;
  98. }
  99. Date date = new Date();
  100. entity.setGmtCreate(date);
  101. entity.setGmtModified(date);
  102. try {
  103. entity = repository.save(entity);
  104. publishRules(entity.getApp());
  105. } catch (Throwable t) {
  106. logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
  107. return Result.ofThrowable(-1, t);
  108. }
  109. return Result.ofSuccess(entity);
  110. }
  111. @PutMapping("/rule/{id}")
  112. @AuthAction(PrivilegeType.WRITE_RULE)
  113. public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id,
  114. @RequestBody DegradeRuleEntity entity) {
  115. if (id == null || id <= 0) {
  116. return Result.ofFail(-1, "id can't be null or negative");
  117. }
  118. DegradeRuleEntity oldEntity = repository.findById(id);
  119. if (oldEntity == null) {
  120. return Result.ofFail(-1, "Degrade rule does not exist, id=" + id);
  121. }
  122. entity.setApp(oldEntity.getApp());
  123. entity.setIp(oldEntity.getIp());
  124. entity.setPort(oldEntity.getPort());
  125. entity.setId(oldEntity.getId());
  126. Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
  127. if (checkResult != null) {
  128. return checkResult;
  129. }
  130. entity.setGmtCreate(oldEntity.getGmtCreate());
  131. entity.setGmtModified(new Date());
  132. try {
  133. entity = repository.save(entity);
  134. publishRules(entity.getApp());
  135. } catch (Throwable t) {
  136. logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
  137. return Result.ofThrowable(-1, t);
  138. }
  139. return Result.ofSuccess(entity);
  140. }
  141. @DeleteMapping("/rule/{id}")
  142. @AuthAction(PrivilegeType.DELETE_RULE)
  143. public Result<Long> delete(@PathVariable("id") Long id) {
  144. if (id == null) {
  145. return Result.ofFail(-1, "id can't be null");
  146. }
  147. DegradeRuleEntity oldEntity = repository.findById(id);
  148. if (oldEntity == null) {
  149. return Result.ofSuccess(null);
  150. }
  151. try {
  152. repository.delete(id);
  153. publishRules(oldEntity.getApp());
  154. } catch (Throwable throwable) {
  155. logger.error("Failed to delete degrade rule, id={}", id, throwable);
  156. return Result.ofThrowable(-1, throwable);
  157. }
  158. return Result.ofSuccess(id);
  159. }
  160. private void publishRules(String app) throws Exception {
  161. List<DegradeRuleEntity> rules = repository.findAllByApp(app);
  162. rulePublisher.publish(app, rules);
  163. }
  164. private <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) {
  165. if (StringUtil.isBlank(entity.getApp())) {
  166. return Result.ofFail(-1, "app can't be blank");
  167. }
  168. if (StringUtil.isBlank(entity.getIp())) {
  169. return Result.ofFail(-1, "ip can't be null or empty");
  170. }
  171. if (entity.getPort() == null || entity.getPort() <= 0) {
  172. return Result.ofFail(-1, "invalid port: " + entity.getPort());
  173. }
  174. if (StringUtil.isBlank(entity.getLimitApp())) {
  175. return Result.ofFail(-1, "limitApp can't be null or empty");
  176. }
  177. if (StringUtil.isBlank(entity.getResource())) {
  178. return Result.ofFail(-1, "resource can't be null or empty");
  179. }
  180. Double threshold = entity.getCount();
  181. if (threshold == null || threshold < 0) {
  182. return Result.ofFail(-1, "invalid threshold: " + threshold);
  183. }
  184. Integer recoveryTimeoutSec = entity.getTimeWindow();
  185. if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) {
  186. return Result.ofFail(-1, "recoveryTimeout should be positive");
  187. }
  188. Integer strategy = entity.getGrade();
  189. if (strategy == null) {
  190. return Result.ofFail(-1, "circuit breaker strategy cannot be null");
  191. }
  192. if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()
  193. || strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
  194. return Result.ofFail(-1, "Invalid circuit breaker strategy: " + strategy);
  195. }
  196. if (entity.getMinRequestAmount() == null || entity.getMinRequestAmount() <= 0) {
  197. return Result.ofFail(-1, "Invalid minRequestAmount");
  198. }
  199. if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) {
  200. return Result.ofFail(-1, "Invalid statInterval");
  201. }
  202. if (strategy == RuleConstant.DEGRADE_GRADE_RT) {
  203. Double slowRatio = entity.getSlowRatioThreshold();
  204. if (slowRatio == null) {
  205. return Result.ofFail(-1, "SlowRatioThreshold is required for slow request ratio strategy");
  206. } else if (slowRatio < 0 || slowRatio > 1) {
  207. return Result.ofFail(-1, "SlowRatioThreshold should be in range: [0.0, 1.0]");
  208. }
  209. } else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
  210. if (threshold > 1) {
  211. return Result.ofFail(-1, "Ratio threshold should be in range: [0.0, 1.0]");
  212. }
  213. }
  214. return null;
  215. }
  216. }

第四步:添加应用服务配置,注意不是sentinel服务的配置。

  1. --- #################### Sentinel配置 ####################
  2. spring:
  3. cloud:
  4. # Sentinel 配置项,对应 SentinelProperties 配置属性类
  5. sentinel:
  6. enabled: true # 是否开启。默认为 true 开启
  7. eager: true # 是否饥饿加载。默认为 false 关闭
  8. transport:
  9. dashboard: 10.205.30.1:7070 # Sentinel 控制台地址
  10. filter:
  11. url-patterns: /** # 拦截请求的地址。默认为 /*
  12. datasource:
  13. flow:
  14. nacos:
  15. server-addr: 10.30.225.112:8848
  16. username: nacos
  17. password: nacos
  18. namespace: test
  19. dataId: operation-server-flow-rules
  20. groupId: DEFAULT_GROUP
  21. rule-type: flow
  22. data-type: json
  23. degrade:
  24. nacos:
  25. server-addr: 10.30.225.112:8848
  26. username: nacos
  27. password: nacos
  28. namespace: test
  29. dataId: operation-server-degrade-rules
  30. groupId: DEFAULT_GROUP
  31. rule-type: degrade
  32. data-type: json

效果:

 

 

11.热点,系统,授权同熔断规则 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/512595
推荐阅读
相关标签
  

闽ICP备14008679号