什么是限流

在互联网领域,限流是指对进入系统的请求数量或频率进行控制的一种机制,以防止系统因流量暴增而过载,从而保障系统的稳定性和可用性。

限流目的

  1. 防止系统过载:控制请求速率,避免突发流量导致系统崩溃。
  2. 资源保护:合理分配系统资源,防止某些请求占用过多资源影响其他请求。
  3. 防止恶意攻击:通过限制请求频率,抵御DDoS等恶意攻击。
  4. 保障服务质量:确保系统能为每个请求提供稳定、可靠的服务。
  5. 削峰填谷:在访问高峰期平滑请求曲线,将超出系统承载能力的请求延后处理或拒绝。
  6. 成本控制:对于按量计费的云服务,限流可以有效控制成本。
  7. 公平竞争:确保不同用户或应用程序之间公平地使用系统资源。

应用场景

限流算法

拒绝策略

当请求超过限流阈值时,系统可以采取不同的拒绝策略:

  1. 直接拒绝:返回错误码或错误信息(如HTTP 429 Too Many Requests)。
  2. 丢弃请求:直接丢弃超出的请求,不予处理。
  3. 延迟处理:将请求放入队列,等待系统有空闲资源时再处理。
  4. 降级处理:返回降级后的结果,如使用缓存数据而非实时数据。
  5. 特殊处理:执行特定的代码逻辑,如返回默认值或备选方案。
  6. 调用方熔断:通知调用方暂停发送请求。
  7. 局部熔断:对某些高风险或低优先级的功能进行熔断,暂时停止提供服务。

限流策略

限流策略可以从以下维度考虑,每个维度都包含不同的粒度级别:

  1. 系统架构维度
    • 服务端:
      • 全局级:整个系统的总体流量限制
      • 区域级:针对不同地理区域或数据中心的限流
      • 集群级:分布式系统或微服务集群的流量控制
      • 单机级:单个服务器节点或实例的限流
      • 服务级:特定微服务的流量限制
      • 模块级:技术架构层面的模块限流(如数据访问层、业务逻辑层、展示层)
      • 接口级:特定API接口的调用频率限制
      • 方法级:具体方法或函数的调用频率控制
    • 客户端:
      • IP级:特定IP地址或IP段的请求限制
      • 设备级:不同客户端设备类型(如移动端、PC端)的限流
  2. 业务维度
    • 产品线级:不同产品线或业务线的限流策略
    • 用户账户级:单个用户账户的请求频率限制
    • 用户角色级:基于用户角色(如VIP、普通用户)的差异化限流
    • 操作类型级:不同操作类型(如读、写、删除)的限流
    • 内容类型级:根据处理的内容类型(如文本、图片、视频)设置的限流
    • 业务场景级:特定业务场景(如秒杀、大促)的流量控制
    • 业务功能级:针对特定业务功能(如订单处理、支付、搜索)的限流
  3. 资源维度
    • 缓存级:缓存系统访问的流量控制
    • 数据库级:数据库访问频率的限制
    • 第三方服务级:外部服务或API调用的限流

常用限流策略举例:

  1. 基于用户等级的差异化限流
    • 普通用户:每分钟100次API调用
    • 银牌用户:每分钟300次API调用
    • 金牌用户:每分钟500次API调用
    • VIP用户:每分钟1000次API调用
  2. 基于接口重要性的限流
    • 核心业务接口(如下单):每秒1000次
    • 非核心业务接口(如用户信息查询):每秒500次
    • 管理类接口:每秒100次
  3. 多维度组合限流
    • 单个IP限制:每秒不超过100次请求
    • 单个用户限制:每分钟不超过1000次请求
    • 单个接口限制:每秒不超过10000次请求
    • 整个系统限制:每秒不超过100000次请求
  4. 时间段差异化限流
    • 正常时段(8:00-22:00):系统每秒处理10000次请求
    • 低峰时段(22:00-8:00):系统每秒处理5000次请求
    • 促销活动时段:系统每秒处理20000次请求
  5. 基于资源消耗的自适应限流
    • 当CPU利用率<50%时,允许每秒10000次请求
    • 当CPU利用率在50%-80%时,每秒允许5000次请求
    • 当CPU利用率>80%时,每秒允许1000次请求
  6. 针对特定业务场景的限流
    • 注册接口:每个IP每天最多注册5个账号
    • 登录接口:每个账号每分钟最多尝试5次登录
    • 评论接口:每个用户每分钟最多发布10条评论
  7. 基于地理位置的限流
    • 主要市场(如中国):允许每秒10000次请求
    • 次要市场(如东南亚):允许每秒5000次请求
    • 其他地区:允许每秒1000次请求
  8. 渐进式限流策略
    • 当请求量达到阈值的80%时,开始对非核心业务限流
    • 当请求量达到阈值的90%时,对所有业务实施更严格的限流
    • 当请求量达到阈值的100%时,只保留最核心的业务功能
  9. 基于内容的智能限流
    • 对包含敏感词的内容请求进行更严格的限流
    • 对高频热门内容的请求实施更宽松的限流策略
  10. 结合业务目标的限流
    • 确保支付相关的API永远有30%的处理能力
    • 在促销期间,为商品展示和搜索API预留50%的系统资源

此外,限流策略通常与熔断、降级、负载均衡、缓存等机制结合,构建更健壮的系统,比如:

注意事项

  1. 实施多级限流:从全局到局部,实施多层次的限流策略。
  2. 合理设定限流参数:根据系统容量和业务特性设定合理的限流阈值。
  3. 预留冗余:针对允许一定突发流量的业务,预留适当的冗余容量。
  4. 监控和报警:实时监控限流情况,设置报警机制及时发现问题。
  5. 动态调整:根据业务变化和系统性能,定期审查和调整限流策略。
  6. 确保高可用性:对限流组件进行冗余设计,防止单点故障。
  7. 优化用户体验:提供友好的错误提示,引导用户采取适当行动。
  8. 定期测试和演练:模拟高并发和异常情况,验证限流策略的有效性。
  9. 结合业务场景:针对不同的业务场景和优先级,制定差异化的限流策略。
  10. 日志记录:详细记录限流触发的原因、时间和影响,便于后续分析和优化。

限流是构建高可用、高性能系统的关键技术之一。它通过控制请求速率,有效地保护系统免受过载和恶意攻击的影响。在实际应用中,需要根据具体的业务场景和系统架构,选择合适的限流算法和实现方案。同时,将限流与其他系统保护机制(如熔断、降级)结合使用,可以构建更加健壮和可靠的系统。

面试技巧

15K 回答

(综述)限流是一种非常重要的系统保护机制。它的主要作用是控制系统处理请求的速度,特别是在面对高并发或者资源紧张的情况下。通过限制请求流量,可以有效防止系统过载,保证服务的稳定性和可用性。我个人认为,限流就像是系统的一道防护墙,通过牺牲一部分请求来确保整个系统的正常运行。

(限流目的)说到限流的目的,主要有几个方面:首先是防止系统过载,控制请求速率可以避免突发流量导致系统崩溃。其次是保护系统资源,防止某些请求占用太多资源影响其他请求。还有就是防止恶意攻击,比如DDoS攻击,通过限制请求频率可以起到一定的防御作用。另外,限流还能保障服务质量,确保每个请求都能得到稳定、可靠的服务。在访问高峰期,限流可以帮助我们平滑请求曲线,把超出系统承载能力的请求延后处理或者拒绝掉。对于一些按量计费的云服务,限流还能帮助我们控制成本。最后,限流还能确保不同用户或应用程序之间公平地使用系统资源。

(算法与优缺点)常见的限流算法主要静态和动态算法两类。静态算法主要有四种:固定窗口计数器、滑动窗口计数器、漏桶算法和令牌桶算法。每种算法都有自己的特点和适用场景。比如固定窗口计数器实现简单,性能高,但可能在窗口边界出现突发流量。滑动窗口计数器则能提供更平滑的限流效果,但实现起来稍微复杂一些。漏桶算法适合平滑输出流量,但对突发请求的处理不太友好。令牌桶算法则更灵活,允许一定的突发请求,但需要精确的时间控制。动态算法通常是在静态算法的基础上,根据系统的实时负载状况、关键指标或者优先级来动态调整限流策略。这种方法更加灵活,能够更好地适应系统的实际情况。

(拒绝策略)当请求超过限流阈值时,通常需要相应的拒绝策略。常见的策略包括直接拒绝并返回错误信息,或者将请求放入队列延迟处理,还可以返回降级后的结果,比如使用缓存数据。在一些特殊情况下,我们可能需要执行一些特定的代码逻辑,或者通知调用方暂停发送请求。

(限流维度)在实际应用中,限流策略可以从多个维度考虑,比如系统架构维度、业务维度和资源维度。每个维度都包含不同的粒度级别,比如:从系统架构维度来看,有全局限流、区域限流、集群限流、单机限流等等;从业务维度来看,有用户限流,特定业务限流;从资源维度来看,有对缓存、数据库、第三方服务等资源的访问限流。

此外,限流通常还需要与其他机制结合使用,比如熔断、降级、负载均衡等,以构建更加健壮的系统。举个例子来说,在使用单机限流的情况下,负载均衡器可以在收到限流错误之后,选择另外一个节点重试。

总的来说,限流需要根据具体的业务场景和系统架构来设计并实现。通过合理的限流策略,我们可以有效地提高系统的稳定性和可靠性。

引导点:

限流算法;动态限流算法;拒绝策略;限流结合负载均衡;

25K 回答

在我的实际工作经验中,我使用过以下限流策略:

比如说在 Redis 作为缓存的架构中,当请求达到限流阈值时,可以让这些被限流的请求只访问 Redis,而不再访问后端的主数据库或其他较重的计算逻辑。当然,正常的请求还是走 Redis、数据库这条路。

这种策略的优点是可以大大减轻后端系统的压力,同时还能保证用户快速获得响应。只有恰好 Redis 中没有缓存数据,并且这个请求又是触发了限流的情况,用户会拿不到数据。但是可以预期没有被限流的请求会把缓存重新加载好,保证用户体验。

而在一些可以接受延迟处理的写操作或者复杂计算场景中。当系统达到限流阈值时,我们不会直接拒绝这些请求,而是将它们放入消息队列中,等待系统闲时再进行处理。比如说在通知服务里面,收到发送短信邮件之类的请求的时候,如果此时系统已经负担很重了,那么系统会直接返回已接收的响应,但是其实请求转发到了 Kafka 上。

这种策略的好处是可以削峰填谷,有效地平衡系统负载。对于用户来说,他们的请求没有被直接拒绝,只是处理时间可能会稍长一些。我们通常会给用户一个提示,告诉他们请求已经收到,正在处理中。

在实施这种策略时,我们需要考虑几个关键点:首先是队列的容量控制,防止队列过长导致内存问题;其次是要有合适的消费策略,确保队列中的请求能够及时处理;最后,对于一些有时效性的操作,我们还需要设置过期机制,避免处理已经失去意义的请求。

速记点:

被限流只查询Redis;被限流转异步到 Kafka 上;

35K 回答

从服务治理的角度来说,熔断、限流和降级之间其实并没有什么本质区别。

这三者都可以归类为故障检测-故障处理-故障恢复这一个框架之下。比如说动态限流算法同样可以用于熔断和降级。例如说最简单的内存使用率过高就限流,自然也是可以降级,也可以熔断。

只是说,限流强调的是部分请求还能正常被处理,熔断强调的是防止故障扩散,而降级则是提供有损服务。

引导点:

熔断;降级;

速记点:

熔断、限流和降级,本质一样;

亮 点:

故障检测-故障处理-故障恢复框架

参考


区分偶发性超时和频繁超时的重试策略
ThingsBoard源码中的Security