• Spring Cloud Alibaba整合Sentinel流控


    前面我们都是直接通过集成sentinel的依赖,通过编码的方式配置规则等。对于集成到Spring Cloud中阿里已经有了一套开源框架spring-cloud-alibaba,就是用于将一系列的框架成功的整合到Spring Cloud中。

    我这边Spring Cloud的版本是Finchley.SR2,Spring Boot的版本是2.0.6.RELEASE,下面开始集成步骤。

    1. 整合步骤

    1.1添加Maven依赖

    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    	<version>0.2.1.RELEASE</version>
    </dependency>
    

    1.2 增加限流的配置

    application.properties

    # 文件规则数据源
    spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json
    # JSON格式的数据
    spring.cloud.sentinel.datasource.ds1.file.data-type=json
    # 规则类型
    spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
    

    flowrule.json

    [
      {
        "resource": "hello",
        "controlBehavior": 0,
        "count": 1,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0
      }
    ]
    

    1.3 @SentinelResource使用

    @GetMapping("/test")
    @SentinelResource(value="hello",blockHandler="handleException",blockHandlerClass=ExceptionUtil.class)
    public String test() {
    	String result = restTemplate.getForObject("http://localhost:8087/user/name", String.class);
    	return result;
    }
    

    1.4 回退内容定义

    public class ExceptionUtil {
    	public static String handleException(BlockException ex) {
    		return "扛不住了啊....";
    	}
    }
    

    前面我们使用注解的话都是手动配置SentinelResourceAspect类,为什么今天不需要配置SentinelResourceAspect呢?

    那是因为在spring-cloud-alibaba中已经默认配置好了,代码在org.springframework.cloud.alibaba.sentinel.custom.SentinelAutoConfiguration中,代码如下:

    @Bean
    @ConditionalOnMissingBean
    public SentinelResourceAspect sentinelResourceAspect() {
    	return new SentinelResourceAspect();
    }
    

    2. 整合Apollo持久化规则

    利用spring-cloud-alibaba整合Apollo就比较简单了,直接通过配置就可以,不需要通过编码的方式手动注册动态数据源。

    2.1 增加Apollo的Maven依赖

    <dependency>
    	<groupId>com.alibaba.csp</groupId>
    	<artifactId>sentinel-datasource-apollo</artifactId>
    	<version>1.4.1</version>
    </dependency>
    

    2.2 数据源配置

    # Apollo命名空间
    spring.cloud.sentinel.datasource.ds4.apollo.namespace-name = application
    # 规则配置Key
    spring.cloud.sentinel.datasource.ds4.apollo.flow-rules-key = flowRules
    # 规则配置默认值
    spring.cloud.sentinel.datasource.ds4.apollo.default-flow-rule-value = []
    # 规则类型
    spring.cloud.sentinel.datasource.ds4.apollo.rule-type = flow
    

    2.3 Apollo相关的配置

    关于Apollo的地址,appid等信息可以在配置文件中添加,我们为了演示方便就还是使用代码指定的方式。

    @SpringBootApplication
    public class SentinelApp {
    	public static void main(String[] args) {
            // Apollo 中的应用名称,自己定义的
            String appId = "SampleApp";
            // Apollo 的地址
            String apolloMetaServerAddress = "http://localhost:8080";
            System.setProperty("app.id", appId);
            System.setProperty("apollo.meta", apolloMetaServerAddress);
            // 指定环境
            System.setProperty("env", "DEV");
    		SpringApplication.run(SentinelApp.class, args);
    	}
    }
    

    2.4 测试

    在Apollo中添加限流的规则即可,比如:

    flowRules = [{"grade":1,"count":1,"resource":"hello","controlBehavior":0}]
    

    在org.springframework.cloud.alibaba.sentinel.datasource.converter.JsonConverter中打个端点调试下,启动时或者配置更新时都会在里面进行规则的转换。

    在这边遇到了一个坑跟大家分享一下,最开始我配置了最简单的规则,就下面三个Key

    flowRules = [{"grade":1,"count":1,"resource":"hello"}]
    

    如果配置成上面的三个Key,限流将不会触发,后面自己调试JsonConverter中的代码才发现了原因。

    有这么一段代码,是根据配置中心的json字符串转换成对应的规则类:

    List<AbstractRule> rules = Arrays.asList(convertFlowRule(itemJson),
    						convertDegradeRule(itemJson), convertSystemRule(itemJson),
    						convertAuthorityRule(itemJson), convertParamFlowRule(itemJson));
    

    转换完了后会进行过滤,得到一个最终的List,然后判断数量,只有为1的时候才是正确的,由于我配置上面的规则,然后得出来的convertRuleList里面数量为2,这样就没法返回正确的规则。

    List<AbstractRule> convertRuleList = rules.stream()
    						.filter(rule -> !ObjectUtils.isEmpty(rule))
    						.collect(Collectors.toList());
    
    if (convertRuleList.size() == 0) {
    	logger.warn(
    			"Sentinel JsonConverter can not convert {} to any rules, ignore", itemJson);
    }
    else if (convertRuleList.size() > 1) {
    	logger.warn(
    			"Sentinel JsonConverter convert {} and match multi rules, ignore", itemJson);
    }
    else {
    	ruleList.add(convertRuleList.get(0));
    }
    

    之所有数量为2是因为上面转换代码的convertFlowRule(itemJson)和convertParamFlowRule(itemJson),这两个转换的问题,由于我的配置只有三个key,而这三个Key又是这两个规则共同的,所以都转换成功了才导致数量为2。解决办法就是加一些独有的Key,比如controlBehavior。

    当然这个问题如果我们对接了控制台的话,通过控制台去修改配置中心的值就不会出现这个问题了。但这也是在学习过程中遇到的一个问题,还是得通过调试源码的方式去发现问题的原因。

    欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

    PS:目前星球中正在星主的带领下组队学习Sentinel,等你哦!

    微信扫码加入猿天地知识星球

    猿天地

  • 相关阅读:
    基于session做的权限控制
    spring有关jar包的作用
    Failed to apply plugin [id 'com.android.application'] 和 Could not find com.android.tools.build:gradle:2.XX的最正确的解决方法
    Android Handler机制(四)---Handler源码解析
    System.currentTimeMillis()与SystemClock.uptimeMillis()
    【转】博客美化(6)为你的博文自动添加目录
    Android Handler机制(三)----Looper源码解析
    Android Handler机制(二)---MessageQueue源码解析
    Android Handler机制(一)---Message源码分析
    关于Android Force Close 出现的原因 以及解决方法
  • 原文地址:https://www.cnblogs.com/yinjihuan/p/10748438.html
Copyright © 2020-2023  润新知