服务限流及熔断降级
服务限流
一、作用
通过限制并发访问数或限制一个时间窗口内允许处理的请求数量来保护系统稳定性,通过损失一部分用户的可用性,为大部分用户提供稳定可靠的服务。
二、常见实现
- Nginx层添加限流模块限制平均访问速度
- 限制同一IP地址并发连接数:limit_conn_zone模块
# 指令定义一个 zone,该 zone 存储会话的状态
limit_conn_zone $binary_remote_addr zone=test:10m;
server {
listen 80;
server_name localhost;
location / {
# 该指令用于为一个会话设定最大并发连接数。如果并发请求超过这个限制,那么将返回预定错误
# 此配置示例中,没有显式配置 limit_conn_status 、limit_conn_log_level ,如果没有配置,则启用它们的默认值。
limit_conn test 1;
root html;
index index.html index.htm;
}
- 限制同一IP某段时间的访问量:limit_request模块
# 指令定义一个 zone,生成一个 10M ,名字为 addr 的内存区域,用来存储访问的频次信息
# rate=1r/s,表示允许相同标识的客户端的访问频次,这里限制的是每秒1次
limit_req_zone $binary_remote_addr zone=addr:10m rate=1r/s;
server {
listen 80;
server_name localhost;
location / {
# 设置一个大小为5的缓冲区,当有大量请求过来时,
# 超过访问频次限制 rate=1r/s 的请求可以先放到这个缓冲区内等待,但是这个缓冲区只有5个位置,超过这个缓冲区的请求直接报503并返回。
# 关于 nodelay
# 如果设置,会在瞬间提供处理(rate+burst)个请求的能力,请求超时(rat+burst)的时候直接返回503,永远不存在请求需要等待的情况
# 如果没有设置,则所有请求会依次等待排队;
limit_req zone_addr burst=5 nodelay;
root html;
index index.html index.htm;
}
- 通过limit_rate根据IP限制流量
server {
listen 80;
server_name localhost;
location / {
# 当前请求下载流量到达3m时,触发限速
limit_rate_after 3m;
# 用于指定向客户端一个连接传输数据的速度,速度的单位是每秒传输的字节数
limit_rate 512k;
root html;
index index.html index.htm;
}
-
配置数据库连接池、线程池大小来限制总并发
-
Guava工具包提供的RateLimiter工具类限制接口访问速度:此工具类基于令牌桶算法实现流量限制,通过
RateLimiter.create(1);
创建一个限流器,参数代表每秒生成的令牌数。通过limiter.acquire(i);
以阻塞的方式获取令牌。
也可以通过tryAcquire(int permits, long timeout, TimeUnit unit);
来设置等待超时时间的方式获取令牌,如果timeout为0,则代表非阻塞,获取不到立即返回。 -
TCP通信协议中的流量整形,目标是调整数据传输的平均速率,防止突发性的流量暴增导致网络拥塞和丢包。
三、常用限流算法
计数器算法
- 说明:在指定周期内累加访问次数,当访问次数达到设定的阈值时,触发限流策略,当进入下一个时间周期时进行访问次数的清零。
- 应用:限制同一用户一分钟之内触发短信发送的次数。
- 问题:临界问题,在时间周期界限处(访问次数重置时间点)瞬发访问次数达到阈值。
滑动窗口算法(流量控制)
- 说明:为了解决计数器算法带来的临界问题,引入滑动窗口概念,在固定时间窗口中分割出多个小时间窗口,分别在每个小时间窗口中控制访问次数,再根据时间将窗口往前滑动并删除过期的小时间窗口。最终只需要统计滑动窗口范围内的所有小时间窗口访问总和即可。
- 应用:Sentinel 就是采用滑动窗口算法来实现限流的,其本质就是减小时间间隔,尽可能避免边界问题。
令牌桶限流算法
- 说明:系统会以一个恒定速度往固定容量的令牌桶中放入令牌,当令牌桶装满时会丢弃。对于每一个请求,执行都需要从令牌桶中获得一个令牌,如果没有获得令牌,触发限流策略。
- 场景:
- 请求速度大于令牌生成速度,令牌桶中的令牌很快被消耗玩,后续请求会进入限流状态
- 请求速度等于令牌生成速度,请求执行处于平稳状态
- 请求速度小于令牌生成速度,系统并发不高,请求均能被正常处理,且还可以应对突发新增请求的场景
漏桶限流算法
- 说明:此算法主要控制了数据注入网络的速度,平滑网络上的突发流量。水流流出的效率及速度恒定,无论水流速度多快。多数消息中间件采用了漏桶限流的思想,无论生产者请求量多大,消息的处理能力取决于消费者。
- 场景:
- 请求速度大于流出水滴的速度,即请求数据超出当前服务能出处理的极限,将会触发限流策略
- 请求速度小于等于流出水滴的速度,即服务端的处理能力正好满足客户端的请求需求,请求正常执行
服务熔断及降级
- 熔断:
- 在微服务架构中,由于服务粒度拆分比较细,会出现请求链路较长的情况。在高并发场景中,一旦链路上某个服务不可用,很可能会出现请求堆积从而导致雪崩效应。为防止上述情况的产生,需要暂时将出现故障的接口隔离出来,断绝与外部接口的联系,即触发熔断,此后一段时间内该服务调用者的请求都会直接失败,直到目标服务恢复正常。
- 降级指标:
- 平均响应时间:服务接口的平均响应时间超过阈值,此后的固定时间窗口内的服务请求会自动熔断
- 异常比例:服务接口返回的异常总数比例超过阈值,该服务接口将会自动降级,此后的固定时间窗口中的请求调用会自动返回
- 异常数量:与异常比例类似,服务接口返回的异常数量超过阈值时,触发服务熔断