1. 简介
Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。替换原先Hystrix的位置,
并且 Sentinel 在 Spring Cloud 生态中,不仅补全了 Hystrix 在 Servlet 和 RestTemplate 这一块的空白,而且还完全兼容了 Hystrix 在 FeignClient 中限流降级的用法,并且支持运行时灵活地配置和调整限流降级规则。
Sentinel框架中两个核心概念
1.资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
2.规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
主要特性:
Sentinel 分为两个部分:
向比较Hystrix, Sentinel除了功能更加强大之外, 还提供了非常方便的控制台工具, 可以将集成了核心库的工程注册到控制台,这样我们就可以通过控制台拉取工程的配置,并可以通过图形化界面的方式设置相关的规则,下发到对应的工程
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
2. 基本入门
导入依赖:
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
application.yml:
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
启动类:
@SpringBootApplication
public class MainApp8401 {
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
测试类
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
/**
* 加载此类后执行
*/
@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("testA")
public void testA() {
Entry entry = null;
// 务必保证 finally 会被执行
try {
//自定义的资源名
entry = SphU.entry("HelloWorld");
// 被保护的业务逻辑
System.out.println("业务代码执行完毕!");
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 进行相应的处理操作
System.out.println("此方法被流控");
} finally {
// 务必保证 exit,务必保证每个 entry 与 exit 配对
if (entry != null) {
entry.exit();
}
}
}
}
在此类中,我们首先加载了自定义的受保护资源,并设置了规则为 QPS为2(每秒访问两次),并在代码中使用了Sentinel的限流功能,
下面进行测试:
快速访问接口: http://127.0.0.1:8401/test/testA
可以看到后台打印结果如下:
业务代码执行完毕!
业务代码执行完毕!
此方法被流控
此方法被流控
业务代码执行完毕!
业务代码执行完毕!
此方法被流控
此方法被流控
此方法被流控
此方法被流控
业务代码执行完毕!
业务代码执行完毕!
此方法被流控
此方法被流控
可以发现,访问此资源,已经被流控, 但是这种方式,严重侵入了业务代码,并且比较繁琐, 也可以使用 注解的方式,如下:
注解的方式:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
/**
* 加载此类后执行
*/
@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("业务代码执行完毕!");
}
}
自定义异常处理类:
public class CustomerBlockHandler {
public static void handler(BlockException e) {
System.out.println("方法被流控");
}
}
此时受保护的资源为方法,使用注解的方式,并可以指定统一的异常处理类,和异常处理方法,此方法必须为静态的
这种方式和使用Hystrix的方式类似, 但是每增加一条规则,或修改,都需要改动代码, 这就是Sentinel的强大之处,它提供了控制台的方式,可以动态的添加,修改规则
3. 搭建控制台,并注册客户端
下载地址:https://github.com/alibaba/Sentinel/tags
根据自己集成的Sentinel 版本,下载对应的Dashboard jar包,就是一个boot项目,直接启动即可,可以指定端口号,默认为8080
java -Dserver.port=8080 -jar sentinel-dashboard-1.6.3.jar
启动成功后,访问控制台: http://127.0.0.1:8080/ ,输入账号密码,默认 sentinel/sentinel ,可以看到如下界面
此时,我们需要修改客户端,将其注册到控制中心中:
修改application.yml如下
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
sentinel:
transport: #dashboard地址
dashboard: 127.0.0.1:8080
port: 8719 #默认端口,如果被占用则从8719依次+1扫描
management:
endpoints:
web:
exposure:
include: "*"
指定dashboard地址,并开发/actuator/sentinel
端点
访问: http://127.0.0.1:8401/actuator/sentinel
返回此客户端的Sentinel的各类详细信息:
// 20210301170135
// http://127.0.0.1:8401/actuator/sentinel
{
"blockPage": null,
"appName": "cloudalibaba-sentinel-service",
"consoleServer": "127.0.0.1:8080",
"coldFactor": "3",
"rules": {
"systemRules": [
],
"authorityRule": [
],
"paramFlowRule": [
],
"flowRules": [
{
"resource": "HelloWorld",
"limitApp": "default",
"grade": 1,
"count": 2.0,
"strategy": 0,
"refResource": null,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false,
"clusterConfig": null
}
],
"degradeRules": [
]
},
"metricsFileCharset": "UTF-8",
"filter": {
"order": -2147483648,
"urlPatterns": [
"/*"
],
"enabled": true
},
"totalMetricsFileCount": 6,
"datasource": {
},
"clientIp": "192.168.100.80",
"clientPort": "8719",
"logUsePid": false,
"metricsFileSize": 52428800,
"logDir": "C:\Users\dell\logs\csp\",
"heartbeatIntervalMs": 10000
}
而Dashboard工程也就是靠这个接口,来获取客户端的规则信息的,
当客户端有流量时,查看Dashboard,可以发现此客户端已经注册了进来,并且我们使用代码注册的规则,也被拉取到
4. 流量控制
4.1 概述
流量控制(flow control),其原理是监控应用流量的QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
在控制台,流控规则菜单 -> 新增流控规则,即可对客户端下发一条规则,如下图
-
资源名: 即限流规则的作用对象,对应FlowRule 对象的 resource 字段
-
针对来源: 流控针对的调用来源,填写微服务名,若为 default 则不区分调用来源,都进行流控,对应FlowRule 对象的 limitApp 字段
-
阈值类型(grade)/单机阈值(count):
- QPS: 此资源每秒的请求数达到设置阈值时,触发限流
- 线程数: 此资源并发的线程数达到阈值时,触发限流
-
是否集群: 如果为集群,则设定集群共同分摊分模式
-
流控模式: 调用关系限流策略,对应FlowRule 对象的 strategy 字段
-
直接(默认): 达到限流要求时,直接限流本资源
-
关联: 当关联的资源达到本限流规则后,限流本资源
例如 : 选择关联资源模式后,需要输入关联的资源名,例如 本资源名为A,关联资源为B, 限流QPS为1, 那么当 B资源达到本规则后, 限流A
-
链路:只记录指定资源来源的流量(和针对来源相似,但是是API级别的)
-
-
流控效果: 流量控制效果,对应FlowRule 对象的 controlBehavior 字段
-
直接拒绝: 当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException
-
Warm Up: 即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮
-
会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
-
4.2 演示
默认方式
新增流控的默认方式为新增+直接失败的方式,
在演示之前,先看一下资源名的两种命令方式:
Http接口名的方式:
后端接口:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testB")
public void testA() {
System.out.println("业务代码执行完毕!");
}
}
访问此接口的URL: 127.0.0.1:8401/test/testB
, 此时没有代码注册规则,也没有使用控制台的方式注册,所以怎么访问此接口都不会进行流控,
新增流控:规则为QPS为1,流控的处理为默认
资源名为此接口的URL路径,也是此服务簇点链路上的节点名:
这样,此资源流控的就是此接口了,再测试一下此接口,发现在超出流控规则外的访问,都被拒绝,并返回错误信息:Blocked by Sentinel (flow limiting)
,这也是默认方式的返回结果
指定资源名的方式:
使用上述的方式,只能流控HTTP接口,并且没有办法指定兜底的方法, 所以可以使用这种方式,
首先需要预先绑定方法与资源名:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testD")
@SentinelResource(value = "resourceName",blockHandler = "handler" ,blockHandlerClass = CustomerBlockHandler.class)
public void testD() {
System.out.println("业务代码执行完毕!");
}
}
可以发现,我们指定了某个方法和对应的资源绑定,并且指定了流控的方法, 但是此时代码中并没有注册此资源,测试接口:http://127.0.0.1:8401/test/testD
,发现此接口并没有被流控
所以需要在控制台中添加此流控规则,也使用默认的方式, 并且资源名就为指定的资源名,也就是簇点链路下,/test/testD
节点下的resourceName
节点的名字:
再次访问此接口, 发现此方法已经被流控限制,并且处理的方式为指定的方法: 打印结果如下:
业务代码执行完毕!
方法被流控
方法被流控
业务代码执行完毕!
方法被流控
方法被流控
方法被流控
方法被流控
业务代码执行完毕!
关联
测试接口:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testE")
public void testE() {
System.out.println("业务代码执行完毕!");
}
@GetMapping("testF")
public void testF() {
System.out.println("业务代码执行完毕!");
}
}
新增关联模式的流控规则,如下
本资源名为/test/testE
, 关联的资源为/test/testF
,流控规则为QPS为1;
测试,压测访问/test/testF
,使之触发流控, 但是此接口并没有被限制,正常访问, 但是此时访问/test/testE
, 时,却已经无法访问,
返回错误信息: Blocked by Sentinel (flow limiting)
.
结论: 关联的资源达到流控规则, 才限制本资源
链路
由于从1.6.3 版本开始,Sentinel Web fifilter默认收敛所有URL的入口context,因此链路限流不生效。所以想要使用链路模式
至少sentinel的版本要是 1.7.0 版本即以上(对应SCA的2.1.1.RELEASE)
官方在CommonFilter 引入了 WEB_CONTEXT_UNIFY 参数,用于控制是否收敛context。将其配置为 false 即可根据不同的URL 进行链路限流。
如下配置:
关闭sentinel的CommonFilter的实例化:
spring:
cloud:
sentinel:
filter:
enabled: false
手动注册:
@Configuration
class FilterContextConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
// 入口资源关闭聚合
registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
registration.setName("sentinelFilter");
registration.setOrder(1);
return registration;
}
}
参考:https://github.com/alibaba/sentinel/issues/1213
示例:
配置Service资源:资源名为serviceResource
@Service
public class TestService {
@SentinelResource(value = "serviceResource",blockHandler = "handler" ,blockHandlerClass = CustomerBlockHandler.class)
public void testService() {
System.out.println("服务层业务代码执行成功!");
}
}
共有两个controller资源可以访问:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@Autowired
private TestService testService;
@GetMapping("testG")
public void testG() {
testService.testService();
}
@GetMapping("testH")
public void testH() {
testService.testService();
}
}
新增链路流控如下:
结果: 通过/test/testH
去访问serviceResource
资源,不会被限制.只有通过/test/testG
访问此资源才会被流控
说完了流控模式,再看一下流控效果中,除了快速失败的其他效果
Warm Up预热/冷启动方式
当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。
这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。
冷加载因子:coldFactor 默认为3, 当QPS 达到设定的QPS/coldFactor 时触发冷加载, 此时系统进行流控,拒绝请求,
当等待设定的时间时, 才会恢复设定的QPS
controller:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testI")
public void testI() {
System.out.println("业务代码执行完毕!");
}
}
新增流控:
如上设定,设定的QPS为10, 预热时长为10s, 所以当 QPS 达到 10/3 时,就会进行流控,等待10秒后,才会恢复到正常的QPS
测试:
在初访问资源:http://127.0.0.1:8401/test/testI
时,当QPS 达到3时,系统就进行了流控, 待等到10s后,系统恢复正常的QPS,
排队等待
它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过;否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。
相比较其他的流控效果,同有两个特点:
-
请求通过的严格均匀,例如快速失败,当设定QPS为100时,那么在一秒内前100个请求会通过,不够均匀
而如果是排队等待,则严格限定在100ms内只能通过10个请求
所以这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;
-
不在单一的拒绝请求,而是在指定的时间内可以等待,系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。
controller:
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testJ")
public void testJ() {
System.out.println("业务代码执行完毕!");
}
}
新增流控:
测试:
由于我们设定的超时时间足够的长,此时我们访问资源:http://127.0.0.1:8401/test/testJ
,并没有发生返回错误的情况,只是延时执行了而已,
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
5. 熔断降级
5.1 概述
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。
例如,当调用请求时,超时时间过长, 或者服务出现了异常,此时就不能依靠流量来对此服务进行限制,而是应该立刻熔断降级此服务,
防止请求积压,造成服务雪崩
sentinel供提供了三种策略:
-
RT(慢调用): 默认秒级的统计,当资源在统计时间内的平均响应时间超过阈值之后,资源进入准降级状态。接下来如果持续进入 5 个请求(同时这五个请求的间隔时间也不能过长,否则重新统计),它们的 RT 都持续超过这个阈值,则进行降级
-
异常比例: 默认秒级的统计,即统计一秒内的请求异常比例,超过指定的比例后,进行熔断,异常比率的阈值范围是
[0.0, 1.0]
,代表 0% - 100%。 -
异常数:默认分钟级的统计,当统计时长内的异常数目超过阈值之后会自动进行熔断,
在 1.7 .0后,加入了请求次数的限制,即一秒内需要达到指定的请求数(默认5),否则即使慢调用比例达到,或者异常比例达到(异常数不限),也不进行熔断,
在1.8.0后,可以指定统计时长,可以替换默认的秒级, 例如设置60*1000,则代表分钟级,
在1.8.0后,针对慢调用,熔断的条件为,在统计时间内响应时间超过设定时间的比例,字段:slowRatioThreshold
所以自1.7.0后的降级规则有所改变
具体参考官网:https://github.com/alibaba/Sentinel/wiki/熔断降级
半开状态:
在到达熔断条件后, 接下来的设定的熔断时长内请求会自动被熔断。拒绝请求,经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(对于慢调用,则该请求没有超过指定的时间,对于异常比例和异常数,则此请求没有发生异常)则结束熔断,否则会再次被熔断.(半开状态不会持续很长时间,若在窗口期到达后的一段时间内没有请求过来,一样会恢复)
5.2 演示
RT
controller:响应时间3000ms
@RestController
@RequestMapping("test")
@Slf4j
public class TestController {
@GetMapping("testK")
public void testK() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("业务代码执行完毕!");
}
}
新增降级规则:超时时间为2000ms, 熔断时间为5s,则表示每个请求都将超时
测试:使用压测工具postman或者 jmeter,访问此资源:http://127.0.0.1:8401/test/testK
六次,触发降级,此时再去使用浏览器,会出现如下错误:Blocked by Sentinel (flow limiting)
,等待窗口期过去后,恢复正常,若在半开状态时,继续访问,则又将熔断
异常比例
controller: 若传0,则报错
@GetMapping("testL")
public void testL(Integer i) {
if (i==0){
throw new RuntimeException("错误!");
}
System.out.println("业务代码执行完毕!");
}
新增异常比例为0.5,即错误数/总请求数 大于0.5,则为熔断条件
测试: http://127.0.0.1:8401/test/testL?i=0, 参数为0, 即错误率为100%, 当请求量达到时(时间间隔要短),则进行熔断,返回信息Blocked by Sentinel (flow limiting)
异常数
controller:
@GetMapping("testM")
public void testM(Integer i) {
if (i==0){
throw new RuntimeException("错误!");
}
System.out.println("业务代码执行完毕!");
}
新增降级规则
规则为一分钟内,若异常数达到十个,则进行熔断, 时间窗口为5s, 但是此时若还是在统计时间内熔断,会延续到时间结束,所以时间窗口最好要大于60s
6. 热点规则
6.1 概述
和流量控制类似, 也可以说是精确到参数的流量控制.
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
业务场景: 秒杀业务,比如商城做促销秒杀,针对苹果11(商品id=5)进行9.9秒杀活动,那么这个时候,我们去请
求订单接口(商品id=5)的请求流量十分大,我们就可以通过热点参数规则来控制
商品id=5的请求的并发量。而其他正常商品的请求不会收到限制。
6.2 演示
热点参数的方式,只支持使用@SentinelResource
的编码方式,不支持URL方式
controller:
@GetMapping("testN")
@SentinelResource(value = "hotKeyResource",blockHandler = "hotKeyHandler" ,blockHandlerClass = CustomerBlockHandler.class)
public void testN(Integer p1,String p2) {
System.out.println("业务代码执行完毕!");
}
配置:
入图所示, 新增热点规则名为hotKeyResource, 并且在正常情况下的流控规则为QPS 为3, 熔断时长为2秒,并指定热点参数为索引为0的参数(以方法参数的顺序为准,索引从0开始)
并且添加了对应的热点参数值为10, 并指定类型, 并且此时的限流条件为 QPS 10
测试:
当指定的热点参数不传,为空时,则不会进行流控,例如http://127.0.0.1:8401/test/testN
或者http://127.0.0.1:8401/test/testN?p2=10
,无论访问压力有多大,都不会进行流控,
当指定的热点参数不为空, 但是值不是指定的热点值时,进行普通流控,http://127.0.0.1:8401/test/testN?p1=5&p2=10
, 此url访问时,流控规则为QPS 3, 很轻易的就进入流控
当指定热点参数值为指定的值时,进行特定的热点流控,例如http://127.0.0.1:8401/test/testN?p1=10&p2=10
,此时 为热点参数,QPS为10, 将放大此参数的访问
7. 系统规则
官网: https://github.com/alibaba/Sentinel/wiki/系统自适应限流
系统规则即, Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,
结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护的目的:
- 保证系统不被拖垮
- 在系统稳定的前提下,保持系统的吞吐量
系统规则支持以下的模式:
- Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的
maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。 - CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
控制台新增:
8. 授权规则
官网: https://github.com/alibaba/Sentinel/wiki/黑白名单控制
即配置访问此资源的黑白名单:
很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin
)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。