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

news2024/11/26 9:31:42

背景

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>> {
    @Autowired
    protected ConfigService configService;
    @Autowired
    protected Converter<String, List<T>> converter;

    @Override
    public 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>> {

    @Autowired
    protected ConfigService configService;
    @Autowired
    protected Converter<List<T>, String> converter;

    @Override
    public 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> {

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

    @Override
    public 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:8848
      password: nacos
      username: nacos
      discovery:
        namespace: 1ee594f6-001f-4d68-9852-ca6fce6039c9
        enabled: true
      config:
        namespace: 1ee594f6-001f-4d68-9852-ca6fce6039c9
        enabled: false
        file-extension: yml
    sentinel:
      filter:
        enabled: true
      transport:
        port: 8719
        dashboard: 127.0.0.1:18181
      datasource:
        # 限流
        flow:
          nacos:
            server-addr: ${spring.cloud.nacos.server-addr}
            namespace: ${spring.cloud.nacos.discovery.namespace}
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: flow
        # 熔断
        degrade:
          nacos:
            server-addr: ${spring.cloud.nacos.server-addr}
            namespace: ${spring.cloud.nacos.discovery.namespace}
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade

自定义降级Provider:

/**
 * CustomZuulBlockFallbackProvider
 * @author winfun
 * @since 2023/10/3
 **/
@Slf4j
@Component
public class CustomZuulBlockFallbackProvider implements ZuulBlockFallbackProvider {

    @Override
    public String getRoute() {
        return "*";
    }

    @Override
    public 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.coloradmin.cn/o/1075791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第1讲:MyBatis简介与入门

目录 了解MyBatis掌握MyBatis与Hibernate的区别安装使用MyBatis了解MyBatis的基本构架掌握以XML和Java使用MyBatis掌握MyBatis的XML配置文件的使用完成第一个MyBatis程序的编写 什么是MyBatis MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级…

TortoiseSVN安装教程结合内网穿透实现公网提交文件到本地SVN服务器

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

uni-app:实现滚动条效果

效果 前&#xff08;这里使用到了强制不换行white-space: nowrap;&#xff09; 后 核心代码 overflow: auto; 或 overflow-x: auto; /* 横向滚动条 */ 注&#xff1a;使用 overflow: auto 属性时&#xff0c;如果内容没有超出容器的宽度或高度&#xff0c;则不会显示对应的滚动…

HT8310:内置电荷泵升压音频功放

HT8310具有AB类和D类的自Y切换功能&#xff0c;在受到D类功放EMI干扰困扰时&#xff0c;可随时切换至AB类音频功放模式&#xff08;此时电荷泵升压功能关闭&#xff09;。HT8310内部固定28dB增益&#xff0c;内置的关断功能使待机电流Z小化&#xff0c;还集成了输出端过流保护、…

百度SEO 5个技巧:通过HelpLook让您的文章收录量实现飞跃!

通过百度SEO&#xff0c;可以让百度搜索引擎更好地了解您的网页。比如&#xff1a; 网页上有什么样的内容 网页的内容匹配何种关键词 网页内容对其他有类似问题的用户是否有帮助 当百度判断您的网页符合用户的搜索意图&#xff0c;就会提升您的网页的结果排名&#xff0c;从…

【密码学】Java实现DH函数时出现“Unsupported secret key algorithm: AES“错误

问题描述 jdk版本&#xff1a;8 使用DH和AES算法&#xff0c;实现密钥的交换和加密&#xff0c;测试时报错 java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: AESat com.sun.crypto.provider.DHKeyAgreement.engineGenerateSecret(DHKeyAgreement…

Flutter - 波浪动画和lottie动画的使用

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 波浪动画三方库wave lottie动画 Lottie 是 Airbnb 开发的一款能够为原生应用添加动画效果的开源工具。具有丰富的动画效果和交互功能。 # 波浪动画 https://pub-web…

【计算机网络】poll | epoll

文章目录 1. pollpoll函数参数解析代码解析PollServer代码 poll 特点 2. epoll认识接口epoll_createepoll_ctlepoll_wait 基本原理红黑树就绪队列 1. poll poll函数参数解析 输入 man poll poll的第一个参数是文件描述符 poll的第二个参数为 等待的多个文件描述符(fd)数字层面…

Apache Ranger:(一)安装部署

1.Ranger简介 Apache Ranger提供一个集中式安全管理框架, 并解决授权和审计。它可以对Hadoop生态的组件如HDFS、Yarn、Hive、Hbase等进行细粒度的数据访问控制。通过操作Ranger控制台,管理员可以轻松的通过配置策略来控制用户访问权限。 说白了就是管理大多数框架的授权问题。 …

微信小程序抓包

https://github.com/water-kid/WeChatOpenDevTools 抓包工具 第一次安装成功了&#xff0c;公众号能抓&#xff0c;&#xff0c;小程序报错&#xff0c;&#xff0c;卸载后安装不起了 方法二&#xff1a; 将version.dll 放入 微信所在目录 E:\Program Files\Tencent\WeChat\[…

SpringBoot 如何使用 Ehcache 作为缓存

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

全息投影技术服务公司【盟云全息】收入急剧下降,存在风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 全息投影技术服务公司【盟云全息】MicroCloud Hologram(HOLO)的股价表现今年以来异常出色&#xff0c;年初至今已经上涨了334%以上&#xff0c;猛兽财经将在本文中分析MicroCloud Hologram股价上涨的原因&#xff0c;以及它…

Qt QGridLayout和QFormLayout案例分析

QGridLayout和QFormLayout是Qt中常用的布局管理器&#xff0c;可以用于在应用程序中设置控件的位置和大小。 QGridLayout网格布局(栅格布局) QGridLayout是一个网格布局管理器&#xff0c;可以将控件放置在一个二维网格中。在QGridLayout中&#xff0c;控件可以跨越多个行和列…

2023年中国涂料助剂市场发展历程及趋势分析:中高端助剂市场规模将会迎来新的增长[图]

涂料助剂又称油漆辅料&#xff0c;系配制涂料的辅助材料&#xff0c;能改进涂料性能&#xff0c;促进涂膜形成。种类很多&#xff0c;包括催干剂、增韧剂、乳化剂、增稠剂、颜料分散剂、消泡剂、流平剂、抗结皮剂、消光剂、光稳定剂、防霉剂、抗静电剂等&#xff0c;其中用量最…

2023年中国临床质谱检测行业市场规模及行业竞争格局分析[图]

临床质谱检测是指质谱技术在临床检验中的应用&#xff0c;主要涉及临床生化检验、临床免疫学检验、临床微生物检验以及临床分子生物诊断等多方面&#xff0c;质谱诊断比传统诊断技术更具灵敏性、特异性和准确性&#xff0c;且具有高通量、高效率和低成本的优势。临床质谱技术可…

Allegro 17.2如何直接更新元件封装?

想必很多从事电子设计的小伙伴&#xff0c;都有这样的经历&#xff1a;有些时候原理图和PCB设计是由不同的工程师负责&#xff0c;然后偶尔需要在没有原理图的情况下直接对PCB作品进行操作&#xff0c;如更新元件封装等操作&#xff0c;这种环节不仅费时费力&#xff0c;效率贼…

Table ‘mysql.proc‘ doesn‘t exist

使用workbench 同步model 報錯 "Table ‘mysql.proc‘ doesn‘t exist" 爲什麽會出現這個錯誤&#xff1f; 原因&#xff1a;误删了mysql数据库 解决办法如下&#xff1a; 1、在服务列表里找到mysql&#xff0c;停止服务 2、把mysql文件夹下的data文件夹备份&…

微信小程序--》从模块小程序项目案例23.10.09

配置导航栏 导航栏是小程序的门户&#xff0c;用户进来第一眼看到的便是导航栏&#xff0c;其起着对当前小程序主题的概括。而我们 新建的小程序 时&#xff0c;第一步变开始配置导航栏。如下&#xff1a; 配置tabBar 因为配置tabBar需要借助字体图标&#xff0c;我这里平常喜…

uniapp快速入门系列(3)- CSS技巧与布局

章节三&#xff1a;CSS技巧与布局 1. uniapp中的样式编写2. 常见布局技巧与实例解析2.1 水平居中布局2.2 垂直居中布局2.3 等高布局2.4 响应式布局 3. CSS动画与过渡效果 在uniapp中&#xff0c;我们使用CSS来设置页面的样式和布局。本章将介绍一些在uniapp中常用的CSS技巧和布…

区块链技术在金融领域的应用场景

区块链技术在金融领域具有广泛的应用场景&#xff0c;它可以提供更安全、透明、高效和可信的金融服务。以下是一些区块链金融的主要应用场景&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.数字货币…