跳至主要內容

限流器设计

holic-x...大约 31 分钟架构系统设计

限流器设计

学习核心

  • 限流器
    • ① 什么是限流器?限流器的场景应用?
    • ② 限流器核心
      • 限流算法、限流规则、限流场景
        • 限流算法:固定窗口限流、滑动窗口限流、漏斗桶限流、令牌桶限流
        • 限流规则:一般以配置文件的形式固化到存储中
        • 限流场景:限制API调用频率、限制同一IP单位时间访问次数、避免恶意访问等
      • 单机场景版本 & 分布式场景版本
        • 此处针对的是应用程序界别的限流
        • 考虑分布式场景中的并发和同步问题:竞争条件、数据同步
      • 性能优化:
        • 多数据中心,让分散在不同的区域的客户端可以就近访问到数据中心以提升访问速度
        • 数据的最终一致性同步
      • 监控:对限流数据的收集和分析

学习资料

🟢【限流器】场景核心

1.限流器场景

​ 在网络系统中,限流器被用于控制客户端或服务端发送流量的速率。在HTTP世界中,限流器限制在指定时间内允许发送客户端请求数。 如果API请求次数超过了限流器设置的阈值,则所有超出的调用都会被阻止。

限流器的应用示例:

  • 单个用户每秒最多可以发布2个帖子
  • 每天同一IP地址最多可以创建10个帐户
  • 同一设备每周最多可以领取5次奖励

使用 API 限流器的好处:

  • 防止拒绝服务 (DoS) 攻击造成的资源匮乏
    • 几乎大型科技公司发布的所有 API 都强制执行某种形式的速率限制,例如Twitter将每3小时的推文数量限制为300条;Google docs APIs有如下默认限制:每个用户每60秒读取请求为300次;限流器通过阻止多余的调用来防止DoS攻击
  • 降低成本
    • 限制过多的请求意味着减少服务器数量,将更多资源分配给高优先级的API。 速率限制对于使用付费第三方API的公司来说极为重要。 例如,一些按次数收费的外部API的调用调用场景:检查信用、付款、检索健康记录等,限制调用次数对减少成本至关重要
  • 防止服务器过载
    • 为了减少服务器的负荷,使用限流器来过滤由机器人或用户的不当行为造成的过量请求

2.高并发限流解决方案

​ 随着微服务架构的日益普及,服务之间的依赖和调用关系变得更加复杂,确保服务的稳定性变得尤为关键。在实际业务中,经常会遇到瞬时流量激增的情况,这可能导致请求超时,甚至引发服务器过载和宕机。为了保护系统自身及其上下游服务,通常会采用限流措施,迅速拒绝超过设定上限的请求,保障系统及上下游服务的稳定运行。合理的限流策略可以有效应对流量激增,确保系统的可用性和性能。此处介绍几种常见的限流算法,比较其优缺点,并提供限流算法选择的建议,同时针对业务中的分布式限流提出了多种解决方案

  • 限流解决方案
    • 单机版限流(从原理、实现、优缺点、适用场景等方面展开介绍)
      • 固定窗口限流
      • 滑动窗口限流
      • 漏斗桶限流
      • 令牌桶限流
    • 分布式限流(从实现原理、存在的问题等方面展开介绍)
      • 基于中心化的限流
      • 基于负载均衡的限流
    • 限流设计核心
      • 多级限流
      • 动态阈值调整
      • 解耦设计
      • 高可用性和高容错性
      • 实时监控和报警

① 什么是限流?

​ 限流是高并发场景下,通过控制系统处理请求的速率,迅速拒绝超过设定上限的请求,保障系统及上下游服务的稳定运行的一种服务保护策略。

​ 在限流技术中,需要理解两个主要概念:阈值拒绝策略

  • 阈值:指在单位时间内允许的最大请求量。例如,将QPS(每秒请求数)限制为1000,意味着系统在1秒内最多接受1000次请求。通过设置适当的阈值,可以有效控制系统负载,避免系统因过多请求而崩溃或性能下降
  • 拒绝策略:理超过阈值请求的方法,常见的拒绝策略包括直接拒绝和排队等待
    • 直接拒绝策略会立即拒绝超过阈值的请求,然后直接向用户返回
    • 排队等待策略则将请求放入队列中,按照一定规则处理,避免瞬间拒绝大量请求

​ 选择合适的拒绝策略可以在系统稳定性和用户体验之间取得平衡,能够帮助系统应对突发流量激增、恶意访问或频繁请求的情况,保障系统的稳定性和可用性。限流方案根据实施范围分为单机限流和分布式限流。其中,单机限流根据算法又可以细分为固定窗口、滑动窗口、漏桶和令牌桶等四种常见类型

② 为什么要限流?

​ 限流主要是保证在高并发场景下,可以拒绝掉一部分请求,避免因过载导致系统崩溃或性能下降,从而保证服务能够健康稳定的运行。具体来看,主要有以下一些原因:

  • 防止系统过载
    • 资源保护:当请求量超过系统的处理能力时,CPU、内存、带宽等资源会被迅速消耗,导致系统负载过高甚至崩溃。限流可以防止资源被耗尽,保护系统的正常运行
    • 服务质量:在过载情况下,系统响应时间变长,用户体验变差。限流可以保证在高负载下仍能提供较好的服务质量
  • 提升系统稳定性
    • 预防雪崩效应:如果一个服务过载,会影响其他依赖该服务的系统组件,可能导致整个系统的崩溃。限流可以阻止问题扩散,保持系统稳定性
    • 减少故障传播:当某个服务出现问题时,限流可以防止问题蔓延到其他服务,减少故障范围
  • 应对突发流量
    • 瞬时高峰处理:在特定时间段(如促销活动、突发事件等),请求量可能突然增加。限流可以控制请求速率平稳地处理瞬时高峰
    • 恶意请求防护:限流可以防止恶意用户或攻击者通过大量请求来消耗系统资源,提高系统的安全性

③ 限流基本算法(单机限流)

(1)固定窗口限流(Fixed window counter)

​ 固定窗口限流是最简单直观的一种限流算法,其基本原理是将时间划分为固定大小的窗口,并在每个窗口内限制请求数量或速率。具体来说,就是将请求按照时间顺序放入时间窗口中,并计算该时间窗口内的请求数量,如果请求数量超出了限制,则拒绝该请求

算法步骤:

  • ① 将时间划分为固定大小的窗口,例如每秒一个
  • ② 在每个时间窗口内,记录请求的数量
  • ③ 当新的请求到达时,增加计数器的值加1
  • ④ 如果计数器的值超过了预设的阈值(例如3个请求),则拒绝该请求
  • ⑤ 当时间窗口结束时,重置计数器

​ 如下所示,假设时间窗口长度为1s,限定限流阈值为3,每秒内超过3个以上的请求则直接拒绝

image-20250121160215910

  • 优点:算法实现简单,易于实现和理解

  • 缺点:

    • 请求分布不均匀:在固定窗口算法中,请求在窗口内的分布可能会不均衡,导致某些窗口内的请求量超出阈值,而其他窗口内的请求较少

    • 应对突发流量能力有限:由于固定窗口算法的窗口大小是固定的,无法灵活调整,因此难以应对突发的流量高峰

    • 存在明显的临界问题:在窗口结束时重置请求计数可能会导致处理请求的不公平

      • 比如:限流阀值为每秒5个请求,单位时间窗口为1秒。如果在前0.5秒到1秒的时间内并发5个请求,接着在1秒到1.5秒的时间内又并发5个请求。虽然这两个时间段各自都没有超过限流阈值,但如果计算0.5秒到1.5秒的总请求数,则总共是10个请求,已经远远超过了1秒内不超过5个请求的限流标准

        image-20250121162216597
  • 适用场景:固定窗口算法适合在请求速率有明确要求且流量相对稳定的场景中使用。然而,对于应对突发流量和请求分布不均匀的情况,该算法可能表现不足,此时需要考虑使用其他更灵活的限流算法

(2)滑动窗口限流(Sliding window counter)

​ 滑动窗口其实也是一种通过将时间窗口划分为一个一个小的时间段来限流的方法,每个小的时间段又称之为小周期。相比于固定窗口限流,它可以根据时间滑动删除过期的小周期,以解决固定窗口临界值的问题。比如要限制1s内的请求数量,让时间窗口为1s,在前面固定窗口分析中,会出现临界值问题,比如在0.5s和1.5s之间,这个1s时间段内的请求书就会出现大于阈值情况,那么滑动窗口就可以将1s窗口划分长两个小周期,每个0.5s。每隔0.5s,就往右滑动一个小周期,这样统计的整个窗口大小仍然是1s,只是过期的左边的那个小周期会随着时间删除,这样整个1s的统计周期就是随时间滑动的

image-20250121162544218

​ 基于此,在【固定窗口】中出现的临界问题,例如0.5s-1.5s这1s内来了10个请求,由于滑动窗口会统计到这个时间段,就会拒绝多余请求

  • 优点:

    • 精度高,可以通过调整时间窗口小周期的大小来实现不同的限流效果,小周期的时间跨度越短,精度越高
    • 简单易实现
    • 灵活性高,滑动窗口算法能够根据实际情况动态调整窗口大小,从而适应流量变化,以更好的应对突发流量和请求分布不均匀的情况
  • 缺点:

    • 滑动窗口算法本质上是固定窗口算法的细化版本,它能够在一定程度上提高限流的精度和实时性,但不能彻底解决请求分布不均匀的问题
    • 算法依赖于窗口的大小和时间间隔,特别是在突发流量过大或请求分布极度不均匀的极端情况下,仍可能导致限流不准确
      • 假设窗口以0.5s为小周期移动,如下图,在【0.5s,1.5s】,【1.5s,2.5s】间其实都是合理的,不会有流量超出,但是其实在【0.8s,1.8s】间就有10个请求了,并没有达到限流效果。也就是说其限流精确度受限于小周期的设置 image-20250121163527061
  • 适用场景:同样使用与流量相对稳定的场景。滑动窗口的本质在于将窗口粒度拆分更小,但不管怎样都是基于窗口限制,因此总是会存在流量不均导致的限流不准确问题

(3)漏斗桶限流(Leaking bucket)

​ 漏斗限流算法的核心思想是将请求存储在一个漏斗中,漏斗以固定的速率漏出请求。如果漏斗被填满,新到达的请求将被丢弃。请求可以以以不定的速率流入漏桶,而漏桶以固定的速率流出,所以漏斗算法可以将突发流量均匀地配,确保系统在稳定的负载下运行

算法步骤:

  • 设置桶的容量:定义服务器在瞬间能够接受的最大请求数
  • 确定处理速率:设定每秒能够处理的请求数
  • 请求处理计算
    • 计算处理完成的请求数:已处理请求数 =(当前请求时间 -上次请求时间) x 处理速率
    • 更新当前请求数:最新的当前请求数 =当前请求数 - 已处理请求数
  • 比较和处理请求
    • 如果当前请求数超过桶的容量,则拒绝本次请求
    • 否则,允许请求通过,并将当前请求数增加1
image-20250121163917782
  • 优点:
    • 平滑处理请求速度:漏斗限流能够有效地平滑限制请求的处理速度,防止瞬间请求过多导致系统崩溃或出现雪崩效应
    • 适应流量变化:可以通过控制请求的处理速度,使系统能够适应不同的流量需求,避免系统过载或资源过度闲置
    • 灵活适应场景:通过调整桶的容量和漏出的速率,漏斗限流可以满足不同的限流需求,灵活适应各种使用场景
  • 缺点:
    • 无法动态调整流量:漏斗的漏出速率是固定的,不够灵活,无法根据实际流量情况进行动态调整
    • 突发流量处理有限:在突发流量过大的情况下,漏斗可能很快被填满,大量请求将被拒绝,可能会导致服务质量下降
  • 适用场景:漏斗可以以平滑的速度处理请求,但是仍然无法很好地应对突发流量,因此还是适用于流量相对稳定的场景
(4)令牌桶限流(Token bucket)

​ 令牌桶算法限流是维护一个固定容量的存放令牌的桶,令牌以固定的速率产生,并放入桶中。每个令牌代表一个请求的许可。当请求到达时,需要从令牌桶中获取一个令牌才能通过。如果令牌桶中没有足够的令牌,则请求被限制或丢弃

算法步骤:

  • ① 桶的容量:定义桶的容量,即服务器在一瞬间最多可以接受的请求数
  • ② 令牌生成速率:定义令牌的生成速率,例如每秒生成的令牌数
  • ③ 计算当前令牌数:
    • 每次请求时,计算桶中剩余的令牌数,也就是当前令牌数
      • (本次请求时间 -上次请求时间) x 令牌生成速率 = 两次请求间隔内生成的令牌数
      • 当前令牌数(本次请求前剩余令牌数) + 请求间隔内生成的令牌数 = 最新的当前令牌数(本次请求后剩余令牌数)
  • ④ 处理请求:
    • 比较当前令牌数是否还有剩余,如果有则令牌数减一,请求得到正常处理
    • 如果令牌耗尽,请求被拒绝
image-20250121164647328
  • 优点

    • 平滑流量:令牌桶算法可以将突发流量平滑地分散在一定时间内,从而避免了流量高峰对系统的冲击。这有助于保持系统的稳定性和响应时间的一致性
    • 灵活性高:通过调整令牌的生成速率和桶的容量,可以灵活地控制流量。这样可以根据不同的需求和场景,优’化系统的性能和资源使用率
    • 允许突发流量:由于令牌可以在桶中积累,当流量突然增大时,如果桶中有足够的令牌,系统可以快速响应这种突发流量,避免请求被立即拒绝。这使得令桶算法特别适合处理具有突发性流量的应用场景
  • 缺点

    • 实现复杂:相对于固定窗口算法等其他限流算法,令牌桶算法的实现较为复杂
  • 适用场景

    • 从令牌桶限流的优缺点就可以看出,令牌桶面对大量请求时具有柔性,且请求处理速度可以随请求速度而变。所以在适用场景上要更加宽泛一些,比如一些需要动态调整限流速率以及一些需要平滑处理突发流量的场景都合适
(5)4种限流算法对比
算法优点缺点适用场景
固定窗口简单易实现应对突发流量能力有限,存在明显的临界问题流量较稳定,不需要请求均匀分布
滑动窗口颗粒度更小,提供平滑的流量控制应对突发流量能力有限,仍存在一定的临界问题流量相对稳定
漏斗桶平滑处理流量,以固定速率消费请求对突发流量处理不够灵活,无法调整请求处理速率需要平滑处理流量的场景
令牌桶平滑处理流量,可以动态调整流量规则,请求处理速度可以随着请求速度变化实现相对复杂需要平滑处理流量,且需要适时调整流量处理速率的场景

④ 分布式限流

​ 上述介绍的限流算法是基于单机版本的限流。所谓单机限流是指在单台服务器上,通过限制其在单位时间内处理的请求数量来防止过载。然而,随着微服务架构的广泛应用,系统服务通常分布在多台服务器上,但节点的应用流量往往不能准确的反应整个系统的流量压力,这时需要分布式限流来确保整个系统的稳定性

(1)基于中心化的限流方案

​ 所谓中心化的限流其实就是将原本设计实现在本地服务的限流操作抽离出来,做成一个中心化的限流器,所有服务共享,这里其实选用一个中心化的组件去实现即可,一般选用redis来实现就很方便

实现步骤:

  • ① 选用一个中心化组件,比如Redis

  • ② 设定限流规则,比如每秒允许的最大请求数(QPS),并将该值存储在Redis中

  • ③ 每当有请求到达时,服务器首先向Redis请求令牌

  • ④ 如果获得令牌,请求可以继续处理;如果未获得令牌,则表示请求被限流,此时可以返回错误信息或提示稍后重试

  • 存在问题

    • 单点故障:所有请求都必须经过Redis处理,因此Redis可能成为整个系统的性能瓶颈。当出现redis故障的时候,将会导致整个系统崩溃,所以可以使用Redis的主从复制或哨兵模式以实现高可用性
    • 网络问题:由于所有的请求都多走了一层redis,所以对网络带宽的依赖会有所增加,果网络带宽有限,可能会导致请求传输速度变慢,从而影响Redis的整体性能
(2)基于负载均衡的限流方案

​ 上述分析了单机版的限流和基于中心化的限流都存在一定的问题,单机版主要是各个节点的流量分布可能不均匀,这将影响到限流阈值的设定,对限流精度造成干扰。而基于中心化的限流方案又会出现单点故障,网络带宽限制等问题。而这里的基于负载均衡的分布式限流其实就是针对单机版限流的一种改进,就是本地限流的基础上加上负载均衡器来均衡流量

实现方案:

  • ① 请求分发:通过负载均衡器或分布式服务发现,将请求均匀地分发到多个机器上。这样,每台机器处理的请求数量大致相同

  • ② 本地限流状态维护:在每台机器上维护一个本地的限流状态,独立地进行限流控制。可以使用令牌桶限流算法来实现这一逻辑

  • ③ 动态调整限流参数:根据每台机器的负载情况(例如CPU和内存使用率),动态调整限流参数:

    • 如果负载过高,降低限流阈值,减少请求处理量
    • 如果负载较低,提高限流阈值,增加请求处理量
  • 存在问题

    • 这种方法虽然加了负载均衡器保证了可以在本地实现限流,解决了分布式场景下的单机限流问题,但是由于引入了负载均衡也是系统的复杂性进一步提高,动态扩缩容的适应性也会变差,当系统需要扩容时,要进行额外的配置调整,确保新加入节点流量的均衡,从而达到限流目的

⑤ 限流核心总结

​ 限流是保障系统稳定和高效运行的重要手段,但是任何解决方案都没有银弹,限流方案同样如此,最优的限流方案因具体需求而异。选择适当的限流策略需要考虑系统需求、现有技术栈、系统负载以及底层性能。只有充分理解每种方案的特性,才能在实际应用中做出最佳选择虽然方案的选择会有多种,但在做限流设计时,一般可以结合以下几点来考虑

要点描述
多级限流可以在应用层、服务层、数据层设置多层限流策略,防止系统过载
动态阈值调整根据实时负载调整限流阈值,灵活应对高低负载限流
解耦设计服务与业务逻辑分离,业务变化时仅调整限流策略
高可用性和容错性限流服务高可用,有效防止因限流器崩溃导致的服务流量过大而宕机
实时监控和报警实时监控限流策略,触发时立即报警,快速处理问题

🚀【限流器】场景实战

1.沟通对齐

​ 此处的沟通对齐方向,主核心方向是需求分析、请求量分析、精准度分析、难点/要点分析,可能还有涉及到其他的一些容量、设计等方面的对齐

① 需求分析

  • 设计的限流器是客户端限流器还是服务端的API限流器?=》服务端的API限流器
  • 限流器是否根据IP、用户ID或者其他属性来限制API请求?=》限流器应该足够灵活,能够支持不同的限流规则集
  • 系统的规模是多少?面向的是初创企业还是拥有庞大用户群体的大公司? =》该系统需能够处理大量的请求
  • 系统是否会在分布式环境下工作?=》限流器会在分布式环境下工作,具体设计为一个服务还是在耦合在应用程序代码则由设计决定
  • 是否需要通知机制?=》需要通知被限流的用户

​ 基于上述问题对齐,可以得到限流器的初步需求概述

  • 准确地限制过多的请求
  • 低延迟:限流器不能降低Http响应时间
  • 尽可能的占用更少的内存
  • 分布式速率限制,要求可以在多个服务器或进程之间共享
  • 异常处理,当用户的请求受到限制时,向用户显示明确的异常信息
  • 高容错性:如果限流器出现任何问题(例如,一个缓存服务器离线),它不会影响整个系统

② 难点/要点分析

(1)限流器放在哪里

​ 可以从客户端、服务端的角度切入,思考限流器应该放在哪个位置实现更为合适:

  • ❌客户端:一般来说,客户端是执行速率限制的不可靠场所,因为客户端请求很容易被恶意用户伪造,且无法控制客户端的实现,所以一般不会将限流器放置在客户端
  • 🟢服务端:可以将限流器放在Server端,经此对请求进行拦截处理
  • 🟢中间件:可以构建一个限流器中间件,用于对API请求进行限制

image-20250121171704011

​ 云微服务已经变得非常流行,限流通常在API网关的组件中实现。API网关是一个完全托管的服务,支持限速、SSL、认证、IP白名单、服务静态内容等。在设计限流器时,要问自己的一个重要问题是:限流器应该在哪里实现,在服务器端还是在网关中?这没有绝对的答案。这取决于公司目前的技术栈、工程资源、优先级、目标等。这里有一些通用的指南:

  • 评估目前的技术栈,如编程语言、缓存服务等。确保你目前的编程语言能够有效地在服务器端实现速率限制
  • 确定适合业务需求的速率限制算法。当你在服务器端实施一切时,你可以完全控制算法。然而,如果你使用第三方网关,你的选择可能是有限的
  • 如果已经使用了微服务架构,并在设计中包含了一个API网关来执行认证、IP白名单等,你可以在API网关上添加一个限流器
  • 建立自己的速率限制服务需要时间。如果你没有足够的工程资源来实现限流器,商业API网关是一个更好的选择
(2)高层次的架构

​ 基于上述对限流算法的分析,本质上需要定义一个计数器跟踪来自同一个用户、IP地址等维度的请求数,如果计数器大于限制阈值则拒绝请求。基于此应该考虑选择哪个存储组件进行处理?

​ 由于磁盘访问速度慢,使用数据库并不是一个好主意。选择内存缓存是因为它速度快并且支持基于时间的过期策略。 Redis 是实现速率限制的一个流行选择。它是一个内存中的存储,提供两个命令:INCREXPIRE

  • INCR:它使存储的计数器加1
  • EXPIRE:它为计数器设置一个超时。如果超时过后,计数器会被自动删除

​ 基于此分析,进一步完善架构设计

image-20250121172757589

2.深入设计(架构设计)

① 限流规则设计

​ 所谓限流规则即一段时间内限定多少个操作。例如系统每天最多允许5条营销信息,用户不允许在1分钟内登录超过5次等。这些限流规则一般是以配置文件的形式保存在磁盘中

  • 超出速率限制:如果一个请求被限制了速率,API会向客户端返回一个HTTP响应代码429(请求太多:too many request)。根据不同的使用情况,可能会将速率受限的请求排队等候以后处理。 例如,如果一些订单由于系统过载而受到速率限制,可以保留这些订单以便以后处理

  • 限流器请求头:作为客户端如果想要知道自己是否被节流,节流的情况?可以通过HTTP响应头中返回的信息来获取,限流器会向客户端返回HTTP标头

    • X-Ratelimit-Remaining:窗口内允许请求的剩余数量
    • X-Ratelimit-limit:它表示客户端在每个时间窗口可以进行多少次调用
    • X-Ratelimit-Retry-After:等待的秒数,直到可以再次提出请求而不被节流

    当用户发送过多请求时,将向客户端返回 429 too many requests 错误和 X-Ratelimit-Retry-After 标头

② 限流器流程设计

  • 规则被存储在磁盘上,workers 经常从磁盘中提取规则,并将其存储在高速缓存中
  • 当客户端向服务器发送请求时,该请求首先被发送到限流中间件
  • 限流中间件从缓存中加载规则。它从Redis缓存中获取计数器和最后一次请求的时间戳。根据响应,限流器决定:
    • 如果请求没有速率限制,它将被转发到API服务器
    • 如果请求受到速率限制,限流器会向客户端返回 429 too many requests 错误。 同时,请求被丢弃或转发到队列

image-20250121173552502

③ 分布式环境下的限流器

​ 构建一个在单个服务器环境下运行的限流器并不困难。然而,将系统扩展到支持多个服务器和并发线程是另一回事。在分布式场景下将面临着两个挑战:竞争条件同步问题

(1)竞争条件

​ 所谓竞争条件,是由于Redis的引入。基于前面图示分析,限流器在【高层次的架构】中的工作原理是:

  • ① 从Redis中读取计数器的值
  • ② 检查(计数器+1)是否超出阈值
  • ③ 如果没有超出阈值则将Redis中的计数器值加1

​ 在整个过程中,高并发环境下则会发生竞争条件(可以理解为这整个不是并不是一个原子性操作),进而引发并发问题。结合下述请求时间线分析,理论上两个请求完成counter的值应该为5,但由于出现了竞争条件,导致counter中的值为4

时间点request Arequest B
① 读取计数器的值为3
① 读取计数器的值为3
② 检查(计数器+1)是否超出阈值(4 未超出阈值)
② 检查(计数器+1)是否超出阈值(4 未超出阈值)
③ 没超出阈值则将Redis中的计数器值加1(此时counter更新后为4)
③ 没超出阈值则将Redis中的计数器值加1(此时counter更新后为4)

​ 为了解决上述问题,是解决竞争条件最明显的解决方案,但使用锁会明显降低系统速度。因此采用另外两种策略来解决问题:

  • ① Lua 脚本
  • ② Redis 中的 sorted sets 数据结构
(2)同步问题

​ 同步问题是分布式环境中要考虑的另一个重要因素。 要支持数百万用户,一个限流器服务器可能不足以处理流量。 当使用多个限流器服务器时,则会面临着数据同步的挑战。

​ 结合下图①分析,客户端 1 将请求发送到限流器 1,客户端 2 将请求发送到限流器 2。 由于 Web 层是无状态的,客户端可以将请求发送到不同的限流器,如图①右侧 如果没有发生同步,限流器 1 不包含有关客户端 2 的任何数据,则限流器无法正常工作。

​ 一般的解决方案是采用粘性会话(允许客户端将流量发送到相同的限流器),但是这个方案是不可取的,因为这种场景既不可扩展又不灵活。一种更好的方案是采用像是Redis这样的集中式数据存储来进行统一存储数据

image-20250122094043903

④ 性能优化

​ 性能优化是系统设计中的一个常见的话题,针对限流器的架构设计可以从以下方面切入

​ ① 多数据中心的设置:多数据中心的设置对限流器至关重要,因为对于远离数据中心的用户来说,延迟很高。大多数云服务提供商在世界各地建立了许多边缘服务器位置(例如,截至2020年5月20日,Cloudflare有194个地理上分布的边缘服务器,流量被自动路由到最近的边缘服务器,以减少延时)

​ ② 用最终的一致性模型来同步数据

⑤ 监控

​ 限流器部分设计完成并应用,最重要的是收集分析数据以检查限流器是否有效,需要确保两个核心是否有效:限流算法限流规则

​ 例如,如果速率限制规则过于严格,则会丢弃许多有效请求。 在这种情况下,想稍微放宽规则。例如注意到当流量突然增加时(如抢购),限流器变得无效。 在这种场景下,可能会更换算法来支持突发流量(例如引入【 令牌桶】限流算法)

⑥ 其他话题讨论

  • 硬件 与 软件限流对比

    • 硬件:请求的数量不能超过阈值
    • 软件:请求可以在短时间内超过阈值
  • 不同级别的限流

    • 此处着重讨论了应用程序级别(HTTP:第 7 层)的限流,可以在其他层应用限流
      • 例如,可以使用Iptables(IP:第3层)按IP地址应用速率限制。 注意:开放系统互连模型(OSI模型)有7层(1-7层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)
  • 避免被限速,使用最佳实践设计客户端

    • 使用客户端缓存,以避免频繁调用API

    • 了解限制,不要在短时间内发送太多请求

    • 包含捕获异常或错误的代码,以便客户端可以从异常中恢复正常

    • 为重试逻辑增加足够的回退时间

3.总结陈述

  • 深刻总结

    • 主要介绍限流器的场景应用和基本设计,着重关注限流算法和限流规则的设计,讨论单机和分布式场景的限流器版本的架构设计(此处是基于应用程序级别的限流),再从性能优化和监控等方面完善限流器功能
  • 要点牵引

    • 限流算法:从基本原理、优缺点、场景适配等多个方面切入对比多个限流算法的特点(固定窗口限流、滑动窗口限流、漏斗桶限流、令牌桶限流)
    • 架构设计:单机版本、分布式场景(并发问题的解决思路)
    • 性能优化:多数据中心、数据的最终一致性同步
    • 监控:监控机制的完善,收集和分析数据信息
  • 收尾请教

🚀实战案例

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3