zoukankan      html  css  js  c++  java
  • sentinel 持久化

    1. 概述

    在前面的关于Sentinel的使用中,可以发现,Sentinel-dashboard配置的规则,在我们的微服务以及控制台重启的时候就清空了,因为他是基于内存的.

    所以我们有必要将规则配置进行持久化, Sentinel 为我们提供了多种方式,多种选择:

    image-20210408135947884

    官方文档:https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel

    而最推荐的方式为Push模式,

    我们可以将规则配置到注册中心中,例如ZooKeeper, Nacos, Apollo等等,当我们的客户端去连接时,将配置信息实时推送到各个客户端,概念图如下:

    image-20210408140336138

    下面以Nacos 为例

    2. 以Nacos演示

    首先我们观察一下,没有注册Nacos的情况

    手动注册规则,并进行访问:

    
    @RestController
    @RequestMapping("test")
    @Slf4j
    public class TestController {
    
        @Autowired
        private TestService testService;
    
        /**
         * 加载此类后执行
         */
        @PostConstruct
        public void init() {
            List<FlowRule> rules = new ArrayList<>();
            //新建一个规则
            FlowRule rule = new FlowRule();
            //保护的资源
            rule.setResource("HelloWorld");
            //设置为QPS的规则类型
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            //值为2,则表示每秒只能访问此资源两次
            rule.setCount(2);
            rules.add(rule);
            //加载此资源
            FlowRuleManager.loadRules(rules);
        }
    
        @GetMapping("testB")
        @SentinelResource(value = "HelloWorld",blockHandler = "handler" ,blockHandlerClass = CustomerBlockHandler.class)
        public void testA() {
            System.out.println("业务代码执行完毕!");
        }
    }
    
    

    打印如下

    业务代码执行完毕!
    业务代码执行完毕!
    方法被流控
    方法被流控
    方法被流控
    方法被流控
    业务代码执行完毕!
    业务代码执行完毕!
    方法被流控
    方法被流控
    

    控制台流控规则显示如下

    image-20210408112155405

    说明此时本地注册的流控规则生效

    使用Nacos配置:

    添加依赖(pom):

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

    添加访问数据源配置(yaml):

    server:
      port: 8401
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        sentinel:
          transport: 
            dashboard: 127.0.0.1:8080
            port: 8719  
          datasource:
            dsl: # 名称随意
              nacos:
                server-addr: 192.168.100.108:8848 # nacos地址
                dataId: cloudalibaba-sentinel-service #nacos配置的dataId
                groupId: DEFAULT_GROUP # nacos配置的groupId
                data_type: json # 配置文件类型
                rule-type: flow #规则类型
    management:
      endpoints:
        web:
          exposure:
            include: "*"
            
    

    此时我们再访问testB 接口,发现此方法已经无法被流控,并且 控制台也没有显示此流控规则了, 说明 我们从Nacos中拉取规则时, 将覆盖本地规则,此时 Nacos 我们还没有配置,则 此时流控为空

    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    

    image-20210408112328895

    在Nacos中添加流控配置:

    配置如下,其中 DataId ,GroupId, 配置类型 ,要和客户端中配置的一致,此流控规则为 QPS 为1

    image-20210408141659632

    [
        {
            "resource":"/retaLimit/byUrl", // 资源名
            "limitApp":"default", //来源应用
            "grade":1, //阈值类型,0 表示线程数,1表示QPS
            "count":1, // 单机阈值
            "strategy":0, // 流控模式, 0表示直接,1表示关联, 2表示链路
            "controlBehavior":0, //流控效果, 0表示快速失败,1表示 Warm Up, 2表示排队等待
            "clusterMode":false //是否集群
        }
    ]
    

    此时客户端不用重启, 将自动将新增的流控规则推送到此客户端中:

    image-20210408142410982

    快速访问流控接口:

    @GetMapping("testD")
        @SentinelResource(value = "/retaLimit/byUrl",blockHandler = "handler" ,blockHandlerClass = CustomerBlockHandler.class)
        public void testD() {
            System.out.println("业务代码执行完毕!");
        }
    

    打印信息如下:

    业务代码执行完毕!
    业务代码执行完毕!
    业务代码执行完毕!
    方法被流控
    方法被流控
    方法被流控
    方法被流控
    业务代码执行完毕!
    方法被流控
    方法被流控
    
    

    说明成功将流控规则从Nacos中拉取下来,并此时重启客户端后,流控规则仍然存在,实现持久化.

    3. 改造Sentinel-dashboard

    在上面的演示中, 我们发现此时的dashboard,仅仅只是变成查看 客户端 从Nacos中拉取下来的配置,并没有连接到Nacos中, 所以当我们从dashboard中添加规则时,并没有将规则持久化到Nacos中, 当我们重启客户端后,dashboard 新增的规则仍然消失,

    但是如果我们每次新增规则,都要以这样新增 JSON的方式,又比较麻烦,所以我们可以将dashboard进行改造,使之新增规则时,同样将规则持久化到Nacos中

    首先,需要将dashboard 的源码下载下来: https://github.com/alibaba/Sentinel/tree/master/sentinel-dashboard (源码下载较慢的话,可以私信或评论发你),并打开(本人下载的是1.8)

    查看源码中,在controller包中,有几个特殊的Controller, 对应着页面中的各个规则的CRUD, 以FlowControllerV1 为例:

    image-20210408185522479

    查看此类,有一个非常重要的字段:

    @Autowired
    private SentinelApiClient sentinelApiClient;
    

    每个Controller 就是通过这个对象, 与Sentinel客户端进行Http交互, 将从页面上增加,删除的操作,通过调用对应的API 来操作对应的客户端;

    例如保存规则的方法中:

    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);
        }
    

    调用了此对象的setFlowRuleOfMachineAsync 方法,一直点进去看,会发现最终发送了一个Http请求,

    executeCommand(new HttpGet(urlBuilder.toString()));
    

    那么其他方法,其他各种规则配置类都是一样, 这样一来, dashboard 将直接与客户端请求HTTP请求, 下面我们进行改造,使之 读取规则从Nacos中读取,保存也往Nacos中保存,.

    开始改造:

    在此源码中,其实已经为我们准备了关于此方面的示例,在test包中,

    image-20210408221341777

    已经有了关于关联Nacos的示例, 其中 FlowRuleNacosProvider 类和FlowRuleNacosPublisher 类分别继承了DynamicRuleProvider接口 和 DynamicRulePublisher 接口, 实现了拉取 和推送的方法, 而这两个类则可以替换FlowControllerV1 类中sentinelApiClient字段, 将这四个类拷贝到 主包中,创建Nacos文件夹:

    image-20210408222032375

    注册类时修Bean的id:

    @Component("myFlowRuleNacosProvider")
    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);
        }
    }
    
    @Component("myFlowRuleNacosPublisher")
    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));
        }
    }
    

    并修改NacosConfig 类, 将Nacos的地址改成自己的地址

    @Configuration
    public class NacosConfig {
    
        @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("192.168.100.108");
        }
    }
    

    并将依赖中,关于nacos持久化的包,test标签注释:

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

    此时,我们只需将所有controller包中的sentinelApiClient ,换成 对应的 Nacos对象即可,例如上面的保存流控规则:

    @RestController
    @RequestMapping(value = "/v1/flow")
    public class FlowControllerV1 {
    
        private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
    
        @Autowired
        private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
    
        @Autowired
        @Qualifier("myFlowRuleNacosProvider")
        private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
        @Autowired
        @Qualifier("myFlowRuleNacosPublisher")
        private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
    
        private void publishRules(/*@NonNull*/ String app) throws Exception {
            List<FlowRuleEntity> rules = repository.findAllByApp(app);
            rulePublisher.publish(app, rules);
        }
    }
    
    

    此时,当我们再保存流控规则时,将调用rulePublisherpublish 方法, 对Nacos进行保存,

    但是不建议修改原生的版本,官方也给我们提供了示例,即v2 包中FlowControllerV2类,此时的接口为 "/v2/flow"

    @RestController
    @RequestMapping(value = "/v2/flow")
    public class FlowControllerV2 
    

    建议将所有的controller拷贝一份v2版本, 下面就着官方的示例,看如何将页面上的 菜单也切换到v2的版本上

    同样,对于前端, 也提供了Demo, 在resources/app/scripts/directives/sidebar/sidebar.html 中,修改流控规则的路由,

    <li ui-sref-active="active" ng-if="!entry.isGateway">
                <a ui-sref="dashboard.flowV1({app: entry.app})">
                  <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
              </li>
    

    修改为

    <a ui-sref="dashboard.flow({app: entry.app})">
    

    路由规则配置在app.js中:

    image-20210408223942858

    那么此时,当点击流控规则按钮时,将跳转到 flow_v2.html中, 而这个html也是提供好的,调用的接口都是 "v2":

    如图:当我们再次点击流控规则时,无论是保存还是获取,都将调用v2的版本,其他页面也以此类推

    image-20210408224116345

    同时,对于客户端,也需要添加指定对应的 dataId 和 GroupId

          datasource:
            dsl:
              nacos:
                server-addr: 192.168.100.109:8848
                dataId: cloudalibaba-sentinel-service
                groupId: DEFAULT_GROUP
                data_type: json
                rule-type: flow
            flow: # 和 改造后的对应
                nacos:
                    server-addr: 192.168.100.109:8848
                    dataId: ${spring.application.name}-flow-rules
                    groupId: SENTINEL_GROUP
                    data_type: json
                    rule-type: flow
    

    上面的介绍中,仅仅只是以流控规则为例, 即FlowControllerV1, 同时,对于Nacos, 也就只创建了FlowRuleNacosProviderFlowRuleNacosPublisher 类, 对于其他 的例如降级规则,系统规则等,都需创建 对应的Nacos替换类, 用于替换相应controller的

    sentinelApiClient 字段, 同时前端页面也是一样.

    还有更简单的方式,是直接使用阿里云提供的服务,具体使用,请自行百度或者查看官网:

    https://github.com/alibaba/Sentinel/wiki/AHAS-Sentinel-控制台

  • 相关阅读:
    Atitit.Java exe bat  作为windows系统服务程序运行
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结
  • 原文地址:https://www.cnblogs.com/xjwhaha/p/14635279.html
Copyright © 2011-2022 走看看