目录

一.限流相关问题概述

为什么使用限流?

限流场景:

限流的处理方式:

限流架构

限流算法

固定窗口算法

滑动窗口算法

漏桶算法

令牌桶算法

限流开源项目

Guava 的 RateLimiter

Bucket4j

Hystrix

Resilience4j

Sentinel限流

常用的限流技术调研对比

二.sentinel集成gateway

1.限流相关概念

2. sentinel介绍及集成gateway

(1)sentinel介绍

(2)sentinel和gateway集成


一.限流相关问题概述

为什么使用限流?

我们每个系统在做压测的时候,都有一个处理峰值,当接近峰值继续接受请求的时候,会导致整个系统响应缓慢;

为了保护系统,需要拒绝处理过载的请求,这就是我们下面介绍的限流,通过设定一个峰值阈值,限制请求达到这个峰值,以此来保护系统;

我们常见的一些中间件比如tomcat,mysql,redis等等都有类似的限制。

限流场景:

  • 限制某个接口一分钟内最多请求 100 次
  • 限制某个用户的下载速度最多 100KB/S
  • 限制某个用户同时只能对某个接口发起 5 路请求
  • 限制某个 IP 来源禁止访问任何请求
  • ...

根据不同的请求者和请求资源,可以组合出不同的限流规则。

可以根据请求者的 IP 来进行限流,或者根据请求对应的用户来限流,又或者根据某个特定的请求参数来限流。

而限流的对象可以是请求的频率,传输的速率,或者并发量等,其中最常见的两个限流对象是请求频率和并发量,他们对应的限流被称为 请求频率限流(Request rate limiting)和 并发量限流(Concurrent requests limiting)。

传输速率限流 在下载场景下比较常用,比如一些资源下载站会限制普通用户的下载速度,只有购买会员才能提速,这种限流的做法实际上和请求频率限流类似,只不过一个限制的是请求量的多少,一个限制的是请求数据报文的大小。

限流几项重要的系统指标

TPS(transport per second)

QPS (query per second)

吞吐量

RT

每秒处理的事务数量 每秒的响应请求数 系统在单位时间内处理请求的数量 系统对请求做出响应的时间

关系:QPS(TPS)= 并发数/平均响应时间 或者 并发数 = QPS*平均响应时间

限流的处理方式:

一般我们有下面三种限流的处理方式:

拒绝服务
排队等待
服务降级

最简单的做法是拒绝服务,直接抛出异常,返回错误信息(比如返回 HTTP 状态码 429 Too Many Requests),或者给前端返回 302 重定向到一个错误页面,提示用户资源没有了或稍后再试。但是对于一些比较重要的接口不能直接拒绝,比如秒杀、下单等接口,我们既不希望用户请求太快,也不希望请求失败,这种情况一般会将请求放到一个消息队列中排队等待,消息队列可以起到削峰和限流的作用。第三种处理方式是服务降级,当触发限流条件时,直接返回兜底数据,比如查询商品库存的接口,可以默认返回有货。

限流的几种方式

熔断

服务降级

延迟处理

特权处理

拒绝流量访问,当系统恢复正常时在关闭熔断 将次要服务降级,停止服务,将系统资源释放出来给核心功能 在前端设置一个流程缓冲池,将所有的流程全部缓冲到这个池子不立即处理,常见队列缓模式处理,服务端处理不及时会丢失部分请求 优先处理需要高保障的请求,其他请求丢去或者延迟处理

限流架构

单机模式的限流非常简单,可以直接基于内存就可以实现,而集群模式的限流必须依赖于某个“中心化”的组件,比如网关或 Redis,从而引出两种不同的限流架构:网关层限流 和 中间件限流。

网关作为整个分布式系统的入口,承担了所有的用户请求,所以在网关中进行限流是最合适不过的。网关层限流有时也被称为 接入层限流。

除了我们使用的 Spring Cloud Gateway,最常用的网关层组件还有 Nginx,可以通过它的 ngx_http_limit_req_module 模块,使用 limit_conn_zone、limit_req_zone、limit_rate 等指令很容易的实现并发量限流、请求频率限流和传输速率限流。

另一种限流架构是中间件限流,可以将限流的逻辑下沉到服务层。但是集群中的每个服务必须将自己的流量信息统一汇总到某个地方供其他服务读取,一般来说用 Redis 的比较多,Redis 提供的过期特性和 lua 脚本执行非常适合做限流。除了 Redis 这种中间件,还有很多类似的分布式缓存系统都可以使用,如 Hazelcast、Apache Ignite、Infinispan 等。我们可以更进一步扩展上面的架构,将网关改为集群模式,虽然这还是网关层限流架构,但是由于网关变成了集群模式,所以网关必须依赖于中间件进行限流,这和上面讨论的中间件限流没有区别。

限流算法

固定窗口算法

最简单的限流算法,根据限流的条件,将请求时间映射到一个时间窗口,使用计数器累加访问次数。

优点:实现简单

缺点:存在严重的临界问题,每过一个时间窗口,计数器会清零,限流效果不够平滑,恶意用户可以利用其绕过规则。在临界点前后发送请求,会使得阈值增加一倍。

滑动窗口算法

为了解决固定窗口算法的临界问题,可以将时间窗口划分成更小的时间窗口,然后随着时间的滑动删除相应的小窗口,而不是直接滑过一个大窗口,这就是滑动窗口算法。我们为每个小时间窗口都设置一个计数器,大时间窗口的总请求次数就是每个小时间窗口的计数器的和。如下图所示,我们的时间窗口是 5 秒,可以按秒进行划分,将其划分成 5 个小窗口,时间每过一秒,时间窗口就滑过一秒:每次处理请求时,都需要计算所有小时间窗口的计数器的和,考虑到性能问题,划分的小时间窗口不宜过多,譬如限流条件是每小时 N 个,可以按分钟划分为 60 个窗口,而不是按秒划分成 3600 个。当然如果不考虑性能问题,划分粒度越细,限流效果就越平滑。相反,如果划分粒度越粗,限流效果就越不精确,出现临界问题的可能性也就越大,当划分粒度为 1 时,滑动窗口算法就退化成了固定窗口算法。由于这两种算法都使用了计数器,所以也被称为 计数器算法(Counters)

进一步思考我们发现,如果划分粒度最粗,也就是只有一个时间窗口时,滑动窗口算法退化成了固定窗口算法;那如果我们把划分粒度调到最细,又会如何呢?那么怎样才能让划分的时间窗口最细呢?时间窗口细到一定地步时,意味着每个时间窗口中只能容纳一个请求,这样我们可以省略计数器,只记录每个请求的时间,然后统计一段时间内的请求数有多少个即可,Redis sorted set 技巧 和Sliding window log 算法。

漏桶算法

除了计数器算法,另一个很自然的限流思路是将所有的请求缓存到一个队列中,然后按某个固定的速度慢慢处理,这其实就是漏桶算法(Leaky Bucket)。漏桶算法假设将请求装到一个桶中,桶的容量为 M,当桶满时,请求被丢弃。在桶的底部有一个洞,桶中的请求像水一样按固定的速度(每秒 r 个)漏出来。我们用下面这个形象的图来表示漏桶算法:桶的上面是个水龙头,我们的请求从水龙头流到桶中,水龙头流出的水速不定,有时快有时慢,这种忽快忽慢的流量叫做 Bursty flow。如果桶中的水满了,多余的水就会溢出去,相当于请求被丢弃。从桶底部漏出的水速是固定不变的,可以看出漏桶算法可以平滑请求的速率。漏桶算法可以通过一个队列来实现,如下图所示:当请求到达时,不直接处理请求,而是将其放入一个队列,然后另一个线程以固定的速率从队列中读取请求并处理,从而达到限流的目的。注意的是这个队列可以有不同的实现方式,比如设置请求的存活时间,或将队列改造成 PriorityQueue,根据请求的优先级排序而不是先进先出。当然队列也有满的时候,如果队列已经满了,那么请求只能被丢弃了。漏桶算法有一个缺陷,在处理突发流量时效率很低,于是人们又想出了下面的令牌桶算法。

令牌桶算法

令牌桶算法(Token Bucket)是目前应用最广泛的一种限流算法,它的基本思想由两部分组成:生成令牌 和 消费令牌。

生成令牌:假设有一个装令牌的桶,最多能装 M 个,然后按某个固定的速度(每秒 r 个)往桶中放入令牌,桶满时不再放入;
消费令牌:我们的每次请求都需要从桶中拿一个令牌才能放行,当桶中没有令牌时即触发限流,这时可以将请求放入一个缓冲队列中排队等待,或者直接拒绝;

在实际的应用中,往往不会直接使用这种原始的令牌桶算法,

一般会在它的基础上作一些改进,比如,填充速率支持动态调整,令牌总数支持透支,基于 Redis 支持分布式限流等,不过总体来说还是符合令牌桶算法的整体框架,我们在后面学习一些开源项目时对此会有更深的体会。

限流开源项目

Guava 的 RateLimiter

Guava 的 RateLimiter 基于令牌桶算法实现,不过在传统的令牌桶算法基础上做了点改进,支持两种不同的限流方式:平滑突发限流(SmoothBursty) 和 平滑预热限流(SmoothWarmingUp)。

Bucket4j

Bucket4j是一个基于令牌桶算法实现的强大的限流库,它不仅支持单机限流,还支持通过诸如 Hazelcast、Ignite、Coherence、Infinispan 或其他兼容 JCache API (JSR 107) 规范的分布式缓存实现分布式限流

Hystrix

Hystrix是一个延迟和容错库,旨在隔离远程系统、服务和第三方库的访问点,停止级联故障,并在故障不可避免的复杂分布式系统中实现恢复能力。

Resilience4j

Resilience4j 是一款轻量级、易使用的高可用框架。用过 Spring Cloud 早期版本的同学肯定都听过 Netflix Hystrix,Resilience4j 的设计灵感就来自于它。自从 Hystrix 停止维护之后,官方也推荐大家使用 Resilience4j 来代替 Hystrix。

Resilience4j 的底层采用 Vavr,这是一个非常轻量级的 Java 函数式库,使得 Resilience4j 非常适合函数式编程。Resilience4j 以装饰器模式提供对函数式接口或 lambda 表达式的封装,提供了一波高可用机制:重试(Retry)、熔断(Circuit Breaker)、限流(Rate Limiter)、限时(Timer Limiter)、隔离(Bulkhead)、缓存(Caceh) 和 降级(Fallback)

还支持并发量限流。不过最大的遗憾是,Resilience4j 不支持分布式限流。

gateway网关的限流

网关自带了限流的功能,但是 Spring Cloud Gateway 自带的限流有很多限制,譬如不支持单机限流,不支持并发量限流,而且它的请求频率限流也是不尽人意,这些都需要我们自己动手来解决

Sentinel限流

强大的流量控制组件,为微服务提供可靠性、弹性和监控,面向云原生微服务的高可用流控防护组件。

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

易用的控制台:

常用的限流技术调研对比

Sentinel

Hystrix(维护状态)

Resilience4j(Spring推荐)

开发者 alibaba Netflix 独立
隔离策略 信号量隔离(并发线程数限流) 线程池隔离/信号量隔离 信号量隔离
熔断降级策略 基于响应时间、异常比率、异常数 基于异常比率 基于异常比率、响应时间
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava) Ring Bit Buffer
动态规则配置 支持多种数据源 支持多种数据源 有限支持
扩展性 多个扩展点 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
限流 基于 QPS,支持基于调用关系的限流 有限的支持 Rate Limiter
流量整形 支持预热模式、匀速器模式、预热排队模式 不支持 简单的 Rate Limiter 模式
系统自适应保护 支持 不支持 不支持
控制台 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 简单的监控查看 不提供控制台,可对接其它监控系统

二.sentinel集成gateway

1.限流相关概念

  • 熔断:停止访问某个下游依赖服务
  • 限流:希望限制请求我服务的流量
  • 切流:
    • 我是多活服务,希望故障时可以切换机房流量:
    • 我是单活服务,希望调整同机房不同集群的流量配比:
  • 开关:服务中某个功能是否开启的配置开关。在 911 平台,也作为一种熔断手段。
  • 自动降级
    • 希望报警时,能触发我的预案降级
    • 希望配置更灵活的自动降级预案:卡尔故障自愈平台

2. sentinel介绍及集成gateway

(1)sentinel介绍

sentinel官网:quick-start

sentinel限流介绍:Sentinel(哨兵) 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

sentinel分为两个部分:
核心库(java客户端):不依赖任何框架,能够运行于所有java运行时环境,同时对dubbo、springCloud等框架也有较好的支持
控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器

sentinel源码:GitHub - alibaba/Sentinel: A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)

源码结构

sentinel-core 核心模块,限流、降级、系统保护等都在这里实现

sentinel-dashboard 控制台模块,可以对连接上的sentinel客户端实现可视化的管理

sentinel-transport 传输模块,提供了基本的监控服务端和客户端的API接口,以及一些基于不同库的实现

sentinel-extension 扩展模块,主要对DataSource进行了部分扩展实现

sentinel-adapter 适配器模块,主要实现了对一些常见框架的适配

sentinel-demo 样例模块,可参考怎么使用sentinel进行限流、降级等

sentinel-benchmark 基准测试模块,对核心代码的精确性提供基准测试

(2)sentinel和gateway集成

sentinel和gateway

sentinel支持spring cloud gateway,zuul等主流的API gateway进行限流

sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:

GatewayFlowRule:网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
ApiDefinition:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫 my_api,请求 path 模式为 /foo/** 和 /baz/** 的都归到 my_api 这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。

网关流控实现原理
当通过 GatewayRuleManager 加载网关流控规则(GatewayFlowRule)时,无论是否针对请求属性进行限流,Sentinel 底层都会将网关流控规则转化为热点参数规则(ParamFlowRule),存储在 GatewayRuleManager 中,与正常的热点参数规则相隔离。转换时 Sentinel 会根据请求属性配置,为网关流控规则设置参数索引(idx),并同步到生成的热点参数规则中。

外部请求进入 API Gateway 时会经过 Sentinel 实现的 filter,其中会依次进行 路由/API 分组匹配、请求属性解析和参数组装。Sentinel 会根据配置的网关流控规则来解析请求属性,并依照参数索引顺序组装参数数组,最终传入 SphU.entry(res, args) 中。Sentinel API Gateway Adapter Common 模块向 Slot Chain 中添加了一个 GatewayFlowSlot,专门用来做网关规则的检查。GatewayFlowSlot 会从 GatewayRuleManager 中提取生成的热点参数规则,根据传入的参数依次进行规则检查。若某条规则不针对请求属性,则会在参数最后一个位置置入预设的常量,达到普通流控的效果。

参考文档

限流常见功能方案

实战 Spring Cloud Gateway 之限流篇_wx5acb795659485的技术博客_51CTO博客

sentinel配置说明

【微服务】(十二)—— Sentinel限流_机智兵的博客-CSDN博客_sentinel链路限流

限流技术调研对比

断路器对比Sentinel、Hystrix、resilience4j_lizz666的博客-CSDN博客_resilience4j和sentinel

sentinel与gateway集成

Sentinel系列(11) - Spring Cloud Gateway整合Sentinel实现网关限流_云烟成雨TD的博客-CSDN博客_sentinel整合gateway

限流与代理网关集成调研及应用相关推荐

  1. java网关限流_基于网关GateWay实现限流-令牌桶 及原理解析

    一.使用流程 1) 引入坐标 org.springframework.boot spring-boot-starter-data-redis-reactive 2.1.3.RELEASE 2) 创建b ...

  2. zuul配置请求拦截_spring cloud网关通过Zuul RateLimit 限流配置

    在平常项目中为了防止一些没有token访问的API被大量无限的调用,需要对一些服务进行API限流.就好比拿一些注册或者发验证码的一些接口,如果被恶意无限的调用,多少会造成一些费用的产生,发短信或者邮件 ...

  3. 微服务网关GateWay 过滤+路由+限流

    文章目录 1 微服务网关概述 2 微服务网关微服务搭建 3 微服务网关跨域 4 微服务网关过滤器 5 微服务网关限流 5.1 思路分析 5.2 令牌桶算法 5.3 网关限流代码实现 1 微服务网关概述 ...

  4. .Netcore 2.0 Ocelot Api网关教程(7)- 限流

    本文介绍Ocelot中的限流,限流允许Api网关控制一段时间内特定api的总访问次数. 限流的使用非常简单,只需要添加配置即可. 1.添加限流 修改 configuration.json 配置文件,对 ...

  5. 【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流

    上篇文章我介绍了如何在网关上增加自定义客户端授权功能,从设计到编码实现,一步一步详细讲解,相信大家也掌握了自定义中间件的开发技巧了,本篇我们将介绍如何实现自定义客户端的限流功能,来进一步完善网关的基础 ...

  6. Sentinel(七)之网关限流

    转载自  网关限流 Sentinel 支持对 Spring Cloud Gateway.Zuul 等主流的 API Gateway 进行限流. Sentinel 1.6.0 引入了 Sentinel ...

  7. Soul网关源码阅读(七)限流插件初探

    Soul网关源码阅读(七)限流插件初探 简介     前面的文章中对处理流程探索的差不多了,今天来探索下限流插件:resilience4j 示例运行 环境配置     启动下MySQL和redis d ...

  8. Sentinel 之 网关限流

    网关限流 该文档来之Sentinel官方文档 Sentinel 支持对 Spring Cloud Gateway.Zuul 等主流的 API Gateway 进行限流. Sentinel 1.6.0 ...

  9. sentinel 网关限流

    sentinel 网关限流 官网:https://sentinelguard.io/zh-cn/docs/api-gateway-flow-control.html 网关限流 sentinel支持对主 ...

最新文章

  1. c文本框只能输入数字_VBA代码限制文本框的输入
  2. OpenCV连接的组件Connected Components的实例(附完整代码)
  3. 【AI测试】机器学习项目的测试,算法测试
  4. 牛客多校2 - Cover the Tree(dfs序)
  5. linux该专接本还是工作_是该专接本还是直接工作?学历和经验哪个重要?
  6. ClickHouse 详细集群部署方案
  7. Windows7旗舰版磁盘分区详解—附分区步骤截图
  8. C++STL::两种方式实现STL容器的reference语义
  9. cml sml区别_如何简单清晰地描述 CAPM 在投资学中的运用,以及 CAL、CML 和 SML 的关系和区别?...
  10. Windows下安装Nginx+php+mysql环境
  11. java基础中如何中断/阻塞线程和使用中断
  12. matlab教程 导入数据,MATLAB数据导入
  13. win10运行程序提示“为了对电脑进行保护,已经阻止此应用” 解决方法
  14. JDK官方下载(旧版本,以前老版本)
  15. java 汉字笔画_java如何获取笔画
  16. @ select 函数使用说明
  17. 京淘商城后台管理系统
  18. 短视频怎么追热点?怎样才能快速涨粉?
  19. Sublime text 3最新版破解方法
  20. 【法律】如何保障企业的合法权益:保密协议模板

热门文章

  1. samba共享盘简单配置共享空间
  2. 免费的 PPT 模版资源
  3. HTML——超文本标记语言
  4. 几款主流的网络仿真软件
  5. 5个小组,只有一个女黑客,他们居然要模仿妲己?
  6. DG(Data Guard)
  7. 几大数学软件各有什么优缺点?
  8. 如何制作Gif动态图
  9. Aria2 RPC接口协议和Java的本地调用实现
  10. Linux网络编程基础:listen函数