接口限流
接口限流
Sentinel
由阿里巴巴中间件团队开发的开源项目,是一种面向分布式微服务架构的轻量级高可用流量控制组件
提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性
sentinel分为两部分:
- sentinel-dashboard(控制面板):提供实时监控之外,还提供了流控规则、熔断规则的在线维护等功能
- 客户端整合:每个微服务客户端都需要整合sentinel的客户端封装与配置,才能将监控信息上报给dashboard展示以及实时的更改限流或熔断规则等。
部署
部署Sentinel Dashboard
下载地址:sentinel-dashboard
运行jar包
1
2
3
4
5
6java -jar sentinel-dashboard-1.8.3.jar
#后面可跟参数
-Dserver.port=8080 #设置端口,默认8080
-Dsentinel.dashboard.auth.username=sentinel #设置用户名, 默认sentinel
-Dsentinel.dashboard.auth.password=123456 #设置密码, 默认sentinel访问
localhost:8080
来打开控制面板
客户端整合Sentinel
导入依赖
1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>配置Sentinel Dashboard的访问地址
1
2
3
4
5
6
7
8
9spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 控制面板端口
application:
name: alibaba-sentinel-rate-limiting # 服务名
server:
port: 8001 # 服务端口编写一个访问的接口
1
2
3
4
5
6
7
8
9
10
11package com.xw.controller;
@Slf4j
@RestController
public class TestController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}访问此接口和控制台
限流
配置限流规则
对访问某个接口的所有请求进行限流
流控模式:
直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认模式。
关联:统计与当前相关的另一个资源,触发阈值时,对当前资源限流。
链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
链路模式中,是对不同来源的两个链路做监控。但是sentinel默认会给进入SpringMVC的所有请求设置同一个root资源,会导致链路模式失效。
我们需要关闭这种对SpringMVC的资源聚合
1
2
3
4spring:
cloud:
sentinel:
web-context-unify: false # 关闭context整合
流控效果:
- 快速失效:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。
- warm up:预热模式,对超出阈值的请求同样是拒绝,并抛出异常。但这种模式阈值会动态变化,从一个较小的值逐渐增加到最大值。
- 排队等待:让所有请求按照先后次序排队执行,两个请求的间隔不能小于指定时长。对流量进行整形,将波动的qps整形成平滑的直线。
配置热点参数限流
粒度更细,对访问某个接口的指定参数进行限流
热点参数限流对默认的SpringMVC是无效的,添加@SentinelResource注解开启热点限流
1
2
3
4
5
6@SentinelResource("hot") //设置资源名
@GetMapping("/hot")
public String hot(@RequestParam String id) {
System.out.println("热点参数");
return "success";
}通过控制面板设置
隔离
对访问某个接口的线程进行限制
FeignClient整合Sentinel
将Feign与Sentinel整合,在Feign里面实现线程隔离和服务熔断。
SpringCloud版本为<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
循环依赖可能是版本问题
Feign整合Sentinel的步骤:
- 在application.yml中配置:feign.sentienl.enable=true
- 给FeignClient编写FallbackFactory并注册为Bean
- 将FallbackFactory配置到FeignClient
在用到feign的类的配置中开启sentinel功能
1
2
3feign:
sentinel:
enabled: true # 开启feign对sentinel的支持编写失败降级逻辑
业务失败后,不能直接报错,而应该返回用户一个友好提示或者默认结果,这个就是失败降级逻辑。
给FeignClient编写失败后的降级逻辑
①方式一:FallbackClass,无法对远程调用的异常做处理
②方式二:FallbackFactory,可以对远程调用的异常做处理
在feign-api包中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package cn.itcast.client.fallback;
@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable throwable) {
return new UserClient() {
@Override
public User findById(Long id) {
log.error("查询用户异常");
return new User();
}
};
}
}将UserClientFallbackFactory注册为一个bean
1
2
3
4
5
6
7public class DefaultFeignConfiguration {
@Bean
public UserClientFallbackFactory userClientFallbackFactory() {
return new UserClientFallbackFactory();
}
}在用到feign的类上记得在启动类上设置默认配置类
1
@EnableFeignClients(clients = {UserClient.class},defaultConfiguration = DefaultFeignConfiguration.class)
在feing-api项目中的UserClient接口中使用UserClientFallbackFactory
1
2
3
4
5
6
7
8package cn.itcast.client;
//注意是fallbackFactory不是fallback
@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}重启服务
线程隔离
线程隔离的两种手段
信号量隔离
线程池隔离
信号量隔离的特点
- 基于计数器模式,简单,开销小,适合高扇出的场景
线程池隔离的特点
- 基于线程池模式,有额外开销,但隔离控制更强
配置隔离规则
熔断
熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。
熔断策略:
- 慢调用:当响应时间大于设定的值(RT)时,为一次慢调用。若慢调用的次数大于设定的阈值,请求数量超过设定的最小数量,则会触发熔断
- 异常比例:单位时间里出现异常的比例大于设置的比例,则会触发熔断
- 异常数: 单位时间里出现异常的比例大于设置的数值,则会触发熔断
配置慢调用
配置异常比例/异常数
授权
授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。
只对有授权的请求提供服务
默认情况下,sentinel对一切请求的来源都被认为是一样的值default。
自定义请求来源解析器
配置授权规则时会根据解析器的返回值来判断请求来源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package cn.itcast.order.sentinel;
/**
* 自定义来源解析器
*/
@Component
public class HeaderOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
//从请求头获取来源信息
String origin = request.getHeader("origin");
//请求头中没有"origin",则默认值为"blank"
if (StringUtil.isEmpty(origin)) {
origin = "blank";
}
return origin;
}
}通过配置,给网关添加过滤器
通过网关的请求都会被加上origin的请求头,值为”gateway”
1
2
3
4
5spring:
cloud:
gateway:
default-filters:
- AddRequestHeader=origin,gateway配置授权规则
自定义异常结果
发生限流、降级、授权拦截时,都会抛出异常到调用方,异常结果都是flow limmiting(限流)
异常种类
异常 | 说明 |
---|---|
FlowException | 限流异常 |
ParamFlowException | 热点参数限流的异常 |
DegradeException | 降级异常 |
AuthorityException | 授权规则异常 |
SystemBlockException | 系统规则异常 |
通过自定义堵塞异常处理器来自定义返回结果
1 |
|