真实面经题目 · 原创解析

服务端限流常见方案有哪些?

服务端限流的核心不是单纯拒绝请求,而是在系统容量有限时,把入口流量、服务调用、关键资源和热点参数控制在可承受范围内,优先保护核心链路稳定性。面试回答应从限流位置、算法模型、分布式实现、限流 key、被限流后的处理、与熔断降级的区别、监控和误伤治理几条线展开。

出现于:阿里巴巴 · 后端开发

60 秒回答模板

服务端限流常见方案可以按三个层次回答。第一是限流位置,入口网关可以做全局限流,应用服务可以做接口或租户维度限流,数据库、线程池、连接池、第三方 API 等关键资源也可以做资源级限流。第二是限流算法,固定窗口实现最简单,用单位时间计数控制访问量,但有窗口边界突刺问题;滑动窗口把时间切成多个小窗口或记录请求时间戳,统计更平滑;令牌桶按固定速率产生令牌,桶容量允许短时突发,适合大多数接口流量;漏桶按固定速率出水,更适合严格控制下游调用速率或削峰排队;并发数限制通过信号量、线程池隔离或连接池上限控制同时执行的请求数,保护慢接口和关键资源。第三是工程落地,单机可以用本地内存、RateLimiter、Sentinel 等,分布式通常用 Redis Lua、网关限流组件或服务治理组件保证原子计数和全局配额。限流 key 要结合业务选择,例如接口、用户、租户、IP、设备、appKey、商品 ID、活动 ID、热点参数等,避免只按 IP 导致 NAT 用户被误伤。请求被限流后可以返回 429、业务错误码、Retry-After、降级数据、排队等待或异步化,但排队必须有长度和超时。还要区分限流和熔断,限流是主动控制流入速度,熔断是下游已经异常时短路失败调用。最后需要监控 QPS、拒绝量、排队时长、成功率、P99 延迟和限流命中 key,支持动态调参、白名单、灰度发布和误伤治理。

考点 限流目标
主线 限流位置
易错点 只罗列固定窗口、滑动窗口、令牌桶、漏桶,不说明它们分别…

深入解析

01

限流目标

限流的目标是让服务在流量超过承载能力时仍然保持可预测的退化,而不是等到线程池、连接池、CPU、数据库或缓存被打满后整体雪崩。回答时应先说明保护对象,包括入口流量、核心接口、慢查询资源、第三方依赖和热点业务参数。好的限流方案通常会区分核心链路和非核心链路,把有限容量优先留给支付、下单、登录等关键路径。

02

限流位置

常见位置有网关层、服务层和资源层。网关层适合做统一入口限流,例如按 IP、用户、租户、appKey、接口路径控制流量,优点是前置拦截、成本低。服务层更懂业务,可以按订单类型、会员等级、活动 ID 做精细策略。资源层用于保护数据库、线程池、连接池、消息队列消费者、第三方 API 等具体瓶颈,避免某个接口绕过入口策略后拖垮共享资源。

03

固定窗口

固定窗口计数器把时间切成固定周期,例如每秒或每分钟一个窗口,在窗口内累计请求数,超过阈值就拒绝。它实现简单,单机用内存计数,分布式可用 Redis 的 INCR 加过期时间完成,适合管理后台、低频接口、粗粒度保护等场景。缺点是窗口边界会产生突刺,例如上一秒末尾和下一秒开头都打满配额,短时间内实际放行量可能接近两倍。

04

滑动窗口

滑动窗口是对固定窗口的改进,做法可以是把一个大窗口拆成多个小格子,随时间移动后统计最近 N 个格子的总量,也可以记录请求时间戳并统计最近一段时间的请求数。它能明显缓解边界突刺,统计粒度越细越平滑,但实现复杂度和存储成本也更高。面试中可以说明它适合对突发更敏感、需要较准确限流的接口,例如登录、短信、领券和秒杀入口。

05

令牌桶

令牌桶按固定速率往桶里放令牌,请求到来时必须拿到令牌才能执行,桶容量决定了允许的短时突发量。它限制的是长期平均速率,同时允许短时间内消耗桶内积累令牌,因此比固定匀速模型更适合真实业务流量。常见参数包括令牌生成速率、桶容量、等待时间和拒绝策略。接口正常有波峰波谷、但系统可以承受一定突发时,令牌桶通常是首选。

06

漏桶排队

漏桶把请求放入队列,再按固定速率处理,核心特点是输出速率稳定。它适合需要严格控制下游调用速度的场景,例如调用有 QPS 限制的第三方服务、写入能力固定的老系统、需要削峰填谷的异步处理。工程上不能把漏桶理解成无限排队,队列长度、最大等待时间、超时丢弃和告警都必须配置,否则请求虽然没有立刻失败,但会堆积成更严重的延迟和内存风险。

07

并发限制

并发数限制关注同一时刻有多少请求正在执行,而不是单位时间来了多少请求。慢接口、数据库查询、文件上传、报表导出和第三方调用,即使 QPS 不高,也可能因为执行时间长而占满线程或连接。常见实现包括信号量、线程池隔离、连接池上限、Bulkhead 舱壁模式和每个资源独立队列。它通常与 QPS 限流组合使用,一个控制进入速度,一个控制执行中的占用量。

08

分布式限流

单机限流只能保护当前实例,服务多副本部署时需要考虑全局配额。常见方案是网关统一限流、Redis Lua 原子计数、Redis 滑动窗口、服务治理组件限流,或本地预分配配额加中心同步。Redis 方案要保证计数和过期原子性,避免先 INCR 后 EXPIRE 失败导致 key 永不过期。高性能场景还要考虑 Redis 热 key、网络抖动、时钟一致性、中心故障时是 fail open 还是 fail close。

09

限流 Key

限流 key 决定了策略是否精准。常见 key 包括接口路径、用户 ID、租户 ID、商户 ID、appKey、设备 ID、IP、地区、商品 ID、活动 ID 和请求参数组合。只按 IP 简单但容易误伤公司出口、校园网、运营商 NAT 后的大量真实用户;只按接口又无法限制单个恶意用户。更合理的方式是多级限流,例如全站总量、接口总量、租户配额、单用户频率和热点参数保护共同生效。

10

治理闭环

限流不是配置一个阈值就结束,还需要被限流后的处理和持续治理。返回可以用 429、业务限流码、Retry-After、降级数据、稍后重试提示,也可以进入有界队列或异步任务。限流和熔断要分清,限流是在流量进入前主动控制,熔断是在下游错误率或延迟异常后短路调用。上线后要监控通过量、拒绝量、排队时长、P95/P99 延迟、命中 key、误伤用户和业务转化损失,并支持灰度、白名单和动态调参。

易错点

  • 只罗列固定窗口、滑动窗口、令牌桶、漏桶,不说明它们分别适合什么生产场景。
  • 把限流和熔断混为一谈,没有说清限流是控制入口流量,熔断是下游异常后的短路保护。
  • 只按 IP 限流,忽略代理、NAT、公司出口网关导致的大量正常用户被误伤。
  • 认为排队就是解决方案,却没有设置队列长度、等待超时、丢弃策略和监控告警。
  • 分布式限流只说用 Redis,没有说明原子性、过期时间、热 key、中心故障和性能开销。
  • 只考虑 QPS 限制,忽略并发数限制,导致慢请求仍然可能占满线程池和连接池。
  • 限流后直接返回 500 或模糊错误,导致上游无法识别限流并产生无效重试。

面试官追问

固定窗口有什么问题,怎么优化?

固定窗口最大的问题是边界突刺。比如每分钟限制 1000 次,如果第一分钟最后一秒进来 1000 次,下一分钟第一秒又进来 1000 次,系统在两秒内实际承受了 2000 次。优化方式是使用滑动窗口,把大窗口拆成多个小窗口滚动统计,或者使用令牌桶控制平均速率并允许有限突发。

令牌桶和漏桶怎么选择?

令牌桶更适合常规业务接口,因为它既限制长期平均速率,又允许桶容量范围内的突发流量,用户体验更自然。漏桶更适合要求输出稳定的场景,例如调用第三方 API、写入固定吞吐的下游系统。简单说,想允许合理突发选令牌桶,想强制匀速消费并削峰选漏桶。

分布式限流如何保证准确?

常见做法是把限流状态放到统一组件中,例如 Redis、网关或服务治理平台。Redis 实现时要用 Lua 脚本把计数、过期、扣减令牌等操作合并为原子操作,避免并发下超发。高并发场景还要处理热 key、网络延迟和中心故障,可以通过本地缓存配额、分片 key、降级策略来平衡准确性和可用性。

限流和熔断有什么区别?

限流是主动控制进入系统的流量,目标是在容量耗尽前保护系统;熔断是当下游依赖已经出现高错误率、高延迟或不可用时,临时短路后续调用,避免调用方继续等待和扩散故障。二者经常配合使用,例如接口入口先限流,下游服务异常时再熔断并返回降级结果。

被限流的请求应该怎么处理?

可以直接拒绝,也可以排队、降级或异步化。直接拒绝通常返回 429、业务错误码和重试间隔,避免上游无脑重试;排队适合短时峰值,但必须有队列长度和等待超时;降级适合读多写少场景,例如返回缓存、默认值或简化结果。关键是让调用方知道失败原因,并保护核心链路。

热点参数限流怎么做?

热点参数限流针对的是某些具体参数突然变热,例如爆款商品 ID、活动 ID、用户 ID 或搜索词。做法是先识别高频参数,再对这些参数设置单独阈值或隔离资源,避免一个热点拖垮整个接口。实现上可以用滑动统计、TopN 统计、服务治理组件或本地加中心规则下发,并配合缓存、队列和降级策略。