乐趣区

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,等你哦!

退出移动版