一、概述
Sentinel是阿里开源的一款面向分布式、多语言异构化服务架构的流量治理组件。
主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
二、核心概念
1、资源
资源是Sentinel中一个非常重要的概念,资源就是Sentinel所保护的对象。
资源可以是一段代码,又或者是一个接口,Sentinel中并没有什么强制规定,但是实际项目中一般以一个接口为一个资源,比如说一个http接口,又或者是rpc接口,它们就是资源,可以被保护。
资源是通过Sentinel的API定义的,每个资源都有一个对应的名称,比如对于一个http接口资源来说,Sentinel默认的资源名称就是请求路径。
2、规则
规则也是一个重要的概念,规则其实比较好理解,比如说要对一个资源进行限流,那么限流的条件就是规则,后面在限流的时候会基于这个规则来判定是否需要限流。
Sentinel的规则分为流量控制规则、熔断降级规则以及系统保护规则,不同的规则实现的效果不一样。
三、Demo
1、基本使用
引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
测试代码
public class SentinelSimpleDemo {
public static void main(String[] args) {
//加载流控规则
initFlowRules();
for (int i = 0; i < 5; i++) {
Entry entry = null;
try {
entry = SphU.entry("sayHello");
//被保护的逻辑
System.out.println("访问sayHello资源");
} catch (BlockException ex) {
System.out.println("被流量控制了,可以进行降级处理");
} finally {
if (entry != null) {
entry.exit();
}
}
}
}
private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
//创建一个流控规则
FlowRule rule = new FlowRule();
//对sayHello这个资源限流
rule.setResource("sayHello");
//基于qps限流
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//qps最大为2,超过2就要被限流
rule.setCount(2);
rules.add(rule);
//设置规则
FlowRuleManager.loadRules(rules);
}
}
测试结果
从结果可以看出,当前两次访问sayHello成功之后,qps达到了2,之后再访问就被限流了,失败了。
2、集成Spring
在实际的项目使用中一般不会直接写上面的那段demo代码,而是集成到Spring环境底下。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
之后提供一个/sayHello接口
@RestController
public class SentinelDemoController {
@GetMapping("/sayHello")
public String sayHello() throws InterruptedException {
return "hello";
}
}
配置文件
server:
port: 9527
spring:
application:
name: SentinelDemo
Sentinel实现了SpringMVC中的HandlerInterceptor接口,在调用Controller接口之前,会将一个调用接口设置为一个资源,代码如下
而getResourceName方法就是获取资源名,其实就是接口的请求路径,比如前面提供的接口路径是/sayHello,那么资源名就是/sayHello。
测试结果
可以看出规则生效了,接口被Sentinel限流了,至于为什么出现这个提示,是因为Sentinel有默认的处理BlockException的机制,就在前面提到的进入资源的后面。
当然,你也可以自定义处理的逻辑,实现BlockExceptionHandler接口就可以了。
虽然上面这种硬编码规则的方式可以使用,但是在实际的项目中,肯定希望能够基于系统当期那运行的状态来动态调整规则,所以Sentinel提供了一个叫Dashboard应用的控制台,可以通过控制台来动态修改规则。
控制台其实就是一个jar包,可以从Sentinel的github仓库上下载,或者是通过从下面这个地址获取。
之后通过java -jar命令启动就可以了,端口默认8080,浏览器访问http://ip:8080/#/login就可以登录控制台了,用户名和密码默认都是sentinel。
此时服务要接入控制台,只需要在配置文件上加上控制台的ip和端口即可
spring:
cloud:
sentinel:
transport:
# 指定控制台的ip和端口
dashboard: localhost:8080
项目刚启动的时候控制台默认是没有数据的,需要访问一下接口,之后就有了。
之后就可以看到/sayHello这个资源,后面就可以通过页面设置规则。