目录

一、概述

1. 为什么需要限流

二、限流算法

1. 计数器算法

2. 漏桶算法

3. 令牌桶算法

四、Gateway 限流

1. 添加依赖

2. 配置文件

3. 限流规则配置类


Spring Cloud Gateway 学习专栏

1. Spring Cloud : Gateway 服务网关认识(一)

2. Spring Cloud :整合Gateway 学习 (二)

3. Spring Cloud:Gateway 路由定义定位器 RouteDefinitionLocator (三)

4. Spring Cloud : Gateway 网关过滤器 GatewayFilter(四)

5. Spring Cloud : Gateway 网关限流(五)

6. Spring Cloud:Gateway 集成 Sentinel (六)

7. Spring Cloud : Gateway Redis动态路由 (七)

8. Spring Cloud : Gateway 整合Swagger (八)

如果发现本文有错误的地方,请大家毫不吝啬,多多指教,欢迎大家评论,谢谢!


一、概述

网关限流,顾名思义,限流就是限制流量,就像你手机卡的流量包总共有 20 个G,流量用完了就没有了,通过手机限流,我们可以限制我们超额使用流量,实际在我们项目中通过限流可以很好控制系统的 QPS,从而达到保护系统的目的。

1. 为什么需要限流

比如 Web 服务,对外 Api,这种类型的服务有以下几种可能导致机器被拖垮;

  • 用户增长过快 (好事)
  • 因为某个热点事件 (微博热搜)
  • 竞争对象爬虫
  • 恶意请求

这些情况都是无法预知的,不知道什么时候会有 10 倍甚至 20 的流量访问,如果真碰上这种情况,扩容是根本来不及的。

二、限流算法

常见的限流算法有:

  • 计数器算法
  • 漏桶 (Leaky Bucket)算法
  • 令牌桶 (Token Bucket)算法

1. 计数器算法

计数器算法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于 A 接口来说,我们 1 分钟的访问次数不能超过 100 个。那么我们可以这么做:在一开始的时候,我们可以设置一个计数器 counter ,每当一个请求过来的时候,counter 就加 1,如果 counter 的值大于 100,并且该请求与第一个请求的间隔时间还在 1 分钟之内,触发限流;如果该请求与第一个请求间隔时间大于 1 分钟,重置 counter 重新计数,具体算法的示意图如下:

这个算法虽然简单,但是有一个致命的问题,我们看下图:

从上图中我们可以看到,假设有一个恶意用户,他在 0:59 时,瞬间发送了 100 个请求,并且 1:00 又瞬间发送了 100 个请求,那么其实这个用户在 1 秒里面,瞬间发送 200 个请求。我们刚才规定是 1 分钟最多 100 个请求,也就是每秒钟最多 100 个请求,用户通过在时间窗口的重置节点突发请求,可以瞬间超过我们的速率限制。用户可能通过算法的这个漏洞,瞬间压垮我们服务。

还存在资源浪费的问题,我们的预期是希望 100 个请求可以均匀分散在这一分钟内,假设 30s 以内我们请求上限了,那么剩余的半分钟服务器就会处于闲置状态,比如下图:

2. 漏桶算法

漏桶算法其实也很简单,可以粗略的认为就是注水漏水的过程,往桶中任意速率流入水,以一定速率流出水,当水超过桶流量则丢弃,因为桶的容量是不变的,保证了整体的速率。

其实从字面就很好理解. 类似生活用到的漏斗, 当客户端请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变.

当水流入速度过大时, 漏斗就会溢出, 同样会造成服务拒绝. 相对于计数器的在恢复期内全部拒绝请求, 因为漏斗桶会以一定的速率消费请求, 这样就能够让后续的请求有机会进入到漏斗桶里面.

漏斗桶的弊端

由于漏斗桶有点类似队列, 先进去才能被消费掉, 如果漏斗桶溢出了, 后续的请求都直接丢弃了, 也就是说漏斗桶是无法短时间应对突发流量的. 对于互联网行业来说, 面对突发流量, 不能一刀切将突发流量全部干掉, 这样会给产品带来口碑上影响. 因此漏斗桶也不是完美的方案.

不过漏斗桶能够限制数据的平均传输速率, 能够满足大部分的使用场景的. 如: 我们可以使用漏斗桶限制论坛发帖频率

3. 令牌桶算法

令牌桶算法是对漏桶算法的一种改进,漏桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,已固定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数量达到上限,就丢弃令牌。

应用场景

桶中一直有大量的可用令牌,这时进来的请求可以直接拿到令牌执行,比如设置 QPS 为 100/s,那么限流器初始化完成一秒后,桶中就已经有 100 个令牌,等服务启动完成对外提供服务时,该限流器可以抵挡瞬时 100 个请求。当桶中没有令牌时,请求会进行等待,最后相当于以一定速率执行。

下面就是一个简单的示意图:

实现关键点:

  1. 初始化固定数量的令牌放入令牌桶中初始化和开启一个定时的任务;
  2. 定时往令牌桶添加令牌提供一个获取令牌的方法;
  3. 获取一个令牌,令牌桶中减一,如果令牌桶中为空,返回失败;

四、Gateway 限流

Spring Cloud Gateway 官方提供了 RequestRateLimiterGatewayFilterFactory 过滤器工厂,使用 RedisLua 脚本实现了令牌桶的方式。

官网文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-redis-ratelimiter 具体实现逻辑在 RequestRateLimiterGatewayFilterFactory 类中,Lua 脚本在如下图所示的源码文件夹中:

1. 添加依赖

 <!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.10.1</version></dependency>

2. 配置文件

server:port: 9000
service-url:user-service: http://localhost:8200spring:application:name: mall-gatewaymain:allow-bean-definition-overriding: true## redis配置redis:database: 0host: 47.103.20.21password: zlp123456port: 6379timeout: 7000cloud:## nacos注册中心nacos:discovery:server-addr: 47.103.20.21:8848## gateway配置gateway:routes:- id: user #路由的ID 保证唯一uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称predicates:# 断言,路径相匹配的进行路由 (谓词)- Path=/user/** # 路径匹配filters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1 # 以恒定速率存入令牌redis-rate-limiter.burstCapacity: 2 # 桶的总容量
#                key-resolver: "#{@pathKeyResolver}" #这个必须要配置,否则返回403 pathKeyResolver
#                key-resolver: "#{@paramsKeyResolver}" #这个必须要配置,否则返回403 paramsKeyReslverkey-resolver: "#{@remoteAddrKeyResolver}" #这个必须要配置,否则返回403 paramsKeyResolver# 将 /user/user/getUserInfo?userId=1 重写为 /user/getUserInfo?userId=1- RewritePath=/user/(?<segment>.*),/$\{segment}

3. 限流规则配置类

/*** 路由限流配置*/
@Configuration
public class KeyResolverConfig {@Bean(value = "remoteAddrKeyResolver")public KeyResolver remoteAddrKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());}//   @Bean(value = "pathKeyResolver")public KeyResolver pathKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getURI().getPath());}// @Bean(value = "paramsKeyResolver")public KeyResolver paramsKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));}}

多次访问:http://127.0.0.1:9000/user/user/getUserInfo?userId=1

Redis 结果如下:


源码地址

mall-gateway 这个项目

https://gitee.com/gaibianzlp/zlp-mall-demo.git


参考链接

1.限流算法之令牌桶法(Java实现)

2. Spring Cloud 系列之 Gateway 服务网关-限流

Spring Cloud :Gateway 网关限流(五)相关推荐

  1. 微服务架构spring cloud - gateway网关限流

    1.算法 在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池.线程池). ...

  2. 实战 Spring Cloud Gateway 之限流篇

    来源:https://www.aneasystone.com/archives/2020/08/spring-cloud-gateway-current-limiting.html 话说在 Sprin ...

  3. spring cloud gateway 之限流篇

    转载请标明出处: https://www.fangzhipeng.com 本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方 ...

  4. 进一步学习spring cloud gateway的 限流熔断

    目前,Spring Cloud Gateway是仅次于Spring Cloud Netflix的第二个最受欢迎的Spring Cloud项目(就GitHub上的星级而言).它是作为Spring Clo ...

  5. spring cloud gateway 之限流篇 1

    转载请标明出处: http://blog.csdn.net/forezp/article/details/85081162 本文出自方志朋的博客 个人博客纯净版:https://www.fangzhi ...

  6. Spring Cloud Gateway(限流)

    在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池.线程池).限制瞬时并 ...

  7. Spirng Cloud 中gateway 网关限流和熔断

    分流:原先数据库只放一个服务器,无论多少个都只能访问这个服务器,访问不了就排队(延迟)(如果同一时间也高并发了那就限流) 限流:同一时间限制访问的人数 限流的算法 漏桶算法:把请求放到一个容器中,控制 ...

  8. gateway网关限流配置

    文章目录 熔断.降级.限流的关系 限流常用算法 令牌漏桶算法 gateway限流配置 代码配置 gateway配置 限流之后HTTP返回结构 限流缘由: 部分接口在某些场景业务下某短时间并发量较高,最 ...

  9. Spring Cloud Gateway网关

    Spring Cloud Gateway网关 1. 简介 Spring Cloud Gateway是Spring官网基于Spring 5.0. Spring Boot 2.0.Project Reac ...

最新文章

  1. 【控制】《最优控制理论与系统》-胡寿松老师-第1章-导论
  2. 2021-02-25
  3. MySQL中用户授权/删除授权的方法
  4. 企业实战(Jenkins+GitLab+SonarQube)_10_Jenkins通过Depoly插件热部署Java程序
  5. 使用 ExceptionDispatchInfo 捕捉并重新抛出异常
  6. graphics | 基础绘图系统(十)——星形图、四瓣图、马赛克图
  7. 快慢指针 —— 链表中点
  8. Selenium 三种等待
  9. 装饰模式(Decorate Pattern)
  10. pcs7 v8.1服务器系统,PCS7 V8.1 SP1 AS PO授权 和OS PO授权和ES PO授权 具体 步骤 越详细越好...
  11. python做词云统计_python词频统计,生成词云
  12. 数据库课程设计专题-数据库课程设计大作业作业列表【建议在校生收藏】
  13. xmpp 即时通讯
  14. 服务器系统用哪个版本好,windows服务器系统哪个版本好用
  15. IM 产品设计思考(3) - 呼叫中心及IVR
  16. 前端培训课随感,传智、千锋、尚硅谷、渡一
  17. 失焦事件及取消失焦事情
  18. Python数据分析——matplotlib
  19. 映射可以多对一吗_【高中数学集合与映射】(一)整数和有理数“一样多”?...
  20. 20220905 buffer overflow detected

热门文章

  1. [国产PLC]耐特来源PLC在锅具旋压机中怎样运用
  2. java面试总结(十)—— 常用技术介绍
  3. 从通信展上的手机看看现在研发手机的难易。
  4. STL纵谈——阅读的重要性
  5. 最新JDK17安装步骤(傻瓜式安装)
  6. SurfaceView 截屏方案
  7. 如何将远程的串口连接到本地
  8. 谷歌地图API 显示地图添加maker点,信息窗体及事件
  9. [创业说]一个人的创业时代
  10. VS2017下DILL动态库的生成和使用