Sentinel Dashboard 接入 Nacos 动态数据源 Zuul 接入 Sentinel 实战

背景

Sentinel Dashboard 默认将限流、熔断等规则保存在内存中,然后同步给连接 Dashboard 的客户端,客户端也是保存在内存中。
那么如果当 Sentinel Dashboard 异常重启,那么之前配置的规则将全部丢失,需要重新进行配置。
其中,Sentinel 本身已经提供第三方组件作为动态数据源,如:Apollo、Nacos、Zookeeper。
因此,我们可以对 Sentinel Dashboard 进行改造,将规则存储在上述的中间件中,保证 Dashboard 重启不会丢失原有的所有规则配置。

改造

下载源码

因为我们需要对 Sentinel Dashboard 进行改造,所以需先下载源码下来,这里选择的版本为:1.8.6
image.png
下载源码后,我们可以发现在test下,是有 Apollo、Nacos 和 Zookeeper 作为数据源的代码,因此我们可以进行借鉴复用。
image.png
因为我们的微服务架构是:Spring Cloud Alibaba 系列的,所以注册中心和配置中心都是使用的 Nacos,所以下面将基于 Nacos 去改造 Sentinel Dashboard。

Sentinel Dashboard 接入 Nacos

test 中,Nacos 是通过调用 ConfigService 去查询规则和保存规则,虽然单元测试中代码仅仅是流控规则的代码,但是我们完全可以借鉴,毕竟现在仅仅是改造规则的保存和查询逻辑,整体方式都是一致的,仅仅需要找到其他规则所在代码,然后做替换即可。

自定义 DynamicRuleProvider & DynamicRulePulisher

DynamicRuleProvider

用于查询规则,我们借鉴 test 代码中的com.alibaba.csp.sentinel.dashboard.rule.nacos.FlowRuleNacosProvider即可,为所有规则都实现一遍,核心逻辑就是使用 Nacos 提供的ConfigService进行查询。

DynamicRulePublisher

用于新增/更新/删除规则,我们借鉴 test 代码中的com.alibaba.csp.sentinel.dashboard.rule.nacos.FlowRuleNacosPublisher即可,为所有规则都实现一遍,核心逻辑就是使用 Nacos 提供的ConfigService进行推送。

实现

由于我们仅仅调整规则的保存/更新/删除和查询逻辑,其余业务逻辑不调整,所以不管是那种规则,调整的逻辑都是一致的,可能不一样的仅仅是以下两点:

  1. 保存在 Nacos 中,不同规则的dataId不一样
  2. 从 Nacos 查询后,转化的实体对象不一致

因此,我们这里针对 Provider 和 Publisher 都抽象一个类,实现核心的保存逻辑和更新逻辑。不同规则只需要继承对应的抽象类,然后具体对应的规则dataId和查询实体泛型。
NacosConfigUtil:

/*** @author Eric Zhao* @since 1.4.0*/
public final class NacosConfigUtil {public static final String GROUP_ID = "SENTINEL_GROUP";// 保存到nacos中的文件后缀public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";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 PARAM_FLOW_DATA_ID_POSTFIX = "-param-flow-rules";public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gw-flow-rules";public static final String GATEWAY_API_FLOW_DATA_ID_POSTFIX = "-gw-api-group-rules";//public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-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() {}
}

NacosRuleProvider:

/*** Nacos RuleProvider 抽象类* @author winfun* @since 2023/9/29**/
public abstract class NacosRuleProvider<T extends RuleEntity>  implements DynamicRuleProvider<List<T>> {@Autowiredprotected ConfigService configService;@Autowiredprotected Converter<String, List<T>> converter;@Overridepublic List<T> getRules(String appName) throws Exception {String rules = configService.getConfig(appName + getDataIdPostfix(),NacosConfigUtil.GROUP_ID, 3000);if (StringUtil.isEmpty(rules)) {return new ArrayList<>();}return converter.convert(rules);}/*** dataId 后缀,参考 com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil* @return dataId 后缀*/public abstract String getDataIdPostfix();
}

NacosRulePublisher:

/*** Nacos RulePublisher 抽象类* @author winfun* @since 2023/9/29**/
public abstract class NacosRulePublisher<T extends RuleEntity> implements DynamicRulePublisher<List<T>> {@Autowiredprotected ConfigService configService;@Autowiredprotected Converter<List<T>, String> converter;@Overridepublic void publish(String app, List<T> rules) throws Exception {AssertUtil.notEmpty(app, "app name cannot be empty");if (rules == null) {return;}configService.publishConfig(app + getDataIdPostfix(),NacosConfigUtil.GROUP_ID, converter.convert(rules));}/*** dataId 后缀,参考 com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil* @return dataId 后缀*/public abstract String getDataIdPostfix();
}

后续不同的规则,分别创建子类继承上面的抽象类即可。
image.png
这里拿网关做例子:

/*** 网关 RulePublisher* @author winfun* @since 2023/9/29**/
@Component("nacosGatewayFlowRulePublisher")
public class NacosGatewayFlowRulePublisher extends NacosRulePublisher<GatewayFlowRuleEntity> {@Overridepublic String getDataIdPostfix() {return NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX;}
}
/*** 网关 RuleProvider* @author winfun* @since 2023/9/29**/
@Component("nacosGatewayFlowRuleProvider")
public class NacosGatewayFlowRuleProvider extends NacosRuleProvider<GatewayFlowRuleEntity> {@Overridepublic String getDataIdPostfix() {return NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX;}
}

Controller 接口调整

上面,我们仅仅为各种规则的保存和查询创建了对应的 RulePublisher 和 RuleProvider,我们还需要对页面的接口进行调整,将接口中保存和查询规则的代码调整。
image.png
改动逻辑:将代码中使用 SentinelApiClient 进行规则查询和保存的逻辑代码,改为 Nacos 对应的 Provider 和 Publisher
其中对应关系:

  1. GatewayApiController:使用 nacosApiDefinitionProvider 和 nacosApiDefinitionPublisher
  2. GatewayFlowRuleController:使用 nacosGatewayFlowRuleProvider 和 nacosGatewayFlowRulePublisher
  3. FlowControllerV2:使用 nacosFlowRuleProvider 和 nacosFlowRulePublisher
  4. AuthorityRuleController:使用 authorityRuleNacosProvider 和 authorityRuleNacosPublisher
  5. DegradeController:使用 nacosDegradeRuleProvider 和 nacosDegradeRulePublisher
  6. ParamFlowRuleController:使用 nacosParamFlowRuleProvider 和 nacosParamFlowRulePublisher
  7. SystemController:使用 nacosSystemRuleProvider 和 nacosSystemRulePublisher

以 GatewayFlowRuleController 为例子:
注释掉 SentinelApiClient,引入对应 Nacos 的 RulePublisher 和 RuleProvider:
image.png
查询代码调整:
image.png
新增/更新/删除代码调整,其实就是更新推送规则的逻辑:
image.png

启动应用

添加 Nacos 配置:

nacos.serverAddr=127.0.0.1:8848
nacos.namespace=1ee594f6-001f-4d68-9852-ca6fce6039c9

groupId默认使用 SENTINEL_GROUP,配置在 NacosConfigUtil 中

启动 Spring 应用:
image.png
应用启动后,由于还没有 Sentinel 客户端接入,因此登录 Web 端后,是没有东西可以显示的。
image.png

Sentinel 客户端接入

这里用 Zuul 网关服务作为例子。

Zuul 网关接入 Sentinel

引入Maven依赖:

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-zuul-adapter</artifactId>
</dependency>
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency><!-- 动态数据源 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<!--  nacos 数据源 -->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

添加配置:

spring:cloud:nacos:server-addr: 127.0.0.1:8848password: nacosusername: nacosdiscovery:namespace: 1ee594f6-001f-4d68-9852-ca6fce6039c9enabled: trueconfig:namespace: 1ee594f6-001f-4d68-9852-ca6fce6039c9enabled: falsefile-extension: ymlsentinel:filter:enabled: truetransport:port: 8719dashboard: 127.0.0.1:18181datasource:# 限流flow:nacos:server-addr: ${spring.cloud.nacos.server-addr}namespace: ${spring.cloud.nacos.discovery.namespace}dataId: ${spring.application.name}-flow-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: flow# 熔断degrade:nacos:server-addr: ${spring.cloud.nacos.server-addr}namespace: ${spring.cloud.nacos.discovery.namespace}dataId: ${spring.application.name}-degrade-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: degrade

自定义降级Provider:

/*** CustomZuulBlockFallbackProvider* @author winfun* @since 2023/10/3**/
@Slf4j
@Component
public class CustomZuulBlockFallbackProvider implements ZuulBlockFallbackProvider {@Overridepublic String getRoute() {return "*";}@Overridepublic BlockResponse fallbackResponse(String route, Throwable cause) {RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();String url = request.getRequestURL().toString();if (cause instanceof FlowException) {log.warn("url:{} 触发限流",url);return new BlockResponse(429, "Sentinel触发限流", route);} else if (cause instanceof DegradeException) {log.warn("url:{} 触发熔断",url);return new BlockResponse(429, "Sentinel触发熔断", route);} else {return new BlockResponse(500, "系统异常", route);}}
}

新增启动 VM 参数,标识此应用是网关:

-Dcsp.sentinel.app.type=1

启动应用,并随便调用一个接口,调用后 Sentinel 客户端就会将相关信息上报给 Sentinel Dashboard:
image.png

设置 Route 类型的限流规则和熔断规则

在 Sentinel Dashboard 新增限流规则和熔断规则:
image.png
image.png
Nacos 在对应的 namespace 中也会出现对应的配置:
image.png
调用报错的接口,当调用第一次失败后,第二次就会触发熔断规则:
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/129772.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言文件操作详解:fgetc,fputc,fgets,fputs,fscanf,,fprintf,fread,fwrite的使用和区别

前言&#xff1a;在对于c语言的学习中&#xff0c;我们为了持续使用一些数据&#xff0c;为了让我们的数据可以在程序退出后仍然保存并且可以使用&#xff0c;我们引入了文件的概念和操作&#xff0c;本文旨在为大家分享在文件操作中常用的输入输出函数的使用方式和技巧&#x…

服务器数据恢复-服务器硬盘指示灯黄灯闪烁的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器面板上的硬盘指示灯显示黄色是一种警告&#xff0c;提示指示灯对应的服务器硬盘已经被服务器识别出存在故障&#xff0c;硬盘即将下线。如果出现这种情况&#xff0c;建议服务器管理员/运维人员及时用完好的硬盘替换显示黄色指示灯对应的…

【Redis】Redis持久化深度解析

原创不易&#xff0c;注重版权。转载请注明原作者和原文链接 文章目录 Redis持久化介绍RDB原理Fork函数与写时复制关于写时复制的思考 RDB相关配置 AOF原理AOF持久化配置AOF文件解读AOF文件修复AOF重写AOF缓冲区与AOF重写缓存区AOF缓冲区可以替代AOF重写缓冲区吗AOF相关配置写后…

外贸客户开发信怎么写?如何撰写营销邮件?

外贸客户开发信模板有哪些&#xff1f;高回复率的开发信技巧&#xff1f; 外贸客户开发信是一项至关重要的工作。这封信通常是你与潜在客户建立联系的第一步&#xff0c;因此必须仔细策划和撰写。蜂邮EDM将介绍如何写一封令人印象深刻的外贸客户开发信&#xff0c;以吸引潜在客…

JVM篇---第八篇

系列文章目录 文章目录 系列文章目录一、虚拟机为什么使用元空间替换了永久代?二、什么是Stop The World ? 什么是OopMap?什么是安全点?三、说一下JVM 的主要组成部分及其作用?一、虚拟机为什么使用元空间替换了永久代? 「什么是元空间?什么是永久代?为什么用元空间代…

pandas读取csv文件(分隔符是一个或者多个空格)

文章目录 问题解决方法1.2. 问题 如果遇到csv文件不是以逗号分隔&#xff0c;也不是以一个空格分隔&#xff0c;也不是 \t 分隔&#xff0c; 但是又是有规律的分隔&#xff0c;就像下面这种 解决方法 查看官方文档 官方文档:https://pandas.pydata.org/pandas-docs/stable/r…

JavaScript系列从入门到精通系列第十六篇:JavaScript使用函数作为属性以及枚举对象中的属性

文章目录 前言 1&#xff1a;对象属性可以是函数 2&#xff1a;对象属性函数被称为方法 一&#xff1a;枚举对象中的属性 1&#xff1a;for...in 枚举对象中的属性 前言 1&#xff1a;对象属性可以是函数 对象的属性值可以是任何的数据类型&#xff0c;也可以是函数。 v…

ELementUI之CURD及表单验证

一.CURD 1.后端CURD实现 RequestMapping("/addBook")ResponseBodypublic JsonResponseBody<?> addBook(Book book){try {bookService.insert(book);return new JsonResponseBody<>("新增书本成功",true,0,null);} catch (Exception e) {e.p…

Android Termux安装MySQL,并使用cpolar实现公网安全远程连接[内网穿透]

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【面试经典150 | 哈希表】赎金信

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;哈希表方法二&#xff1a;数组模拟哈希表 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带…

OSPF的7大状态和5大报文详讲

- Down OSPF的初始状态 - Init 初始化——我刚刚给别人发Hello报文 我们可以将OSPF邻居建立的过程理解为&#xff1a;我和你打招呼&#xff0c;你和我打招呼&#xff0c;然后咱俩成了邻居 比如&#xff1a; R1和R2要建立OSPF邻居 R1给R2发送了Hello报文&#xff0c;但是R1此时…