在分布式系统和高并发架构中,限流(Rate Limiting) 是保护系统不被海量请求冲垮的“保险丝”。作为资深 Java 开发,你不仅要熟悉算法,更要理解它在 网关层(如 Spring Cloud Gateway) 和 应用层(如 Sentinel) 的落地差异。
我们可以从四个维度来深度拆解限流。
1. 四大经典限流算法
这是面试和技术选型的核心,每种算法都有其适用的业务场景:
-
固定窗口(Fixed Window):
-
原理:在固定的时间内(如 1 秒)允许 N 个请求。
-
缺点:存在临界突刺问题。比如在 0.9s 到 1.1s 之间,可能会瞬间涌入 2N 个请求。
-
-
滑动窗口(Sliding Window):
-
原理:将时间划分为更小的格子(如 100ms),窗口随时间向右滑动。
-
优点:解决了固定窗口的临界问题。Sentinel 的底层就大量使用了这种算法。
-
-
漏桶算法(Leaky Bucket):
-
原理:请求像水一样进入漏桶,桶以恒定的速率流出水。
-
优点:强行平滑网络流量。不管进来的请求多猛,出去的速度永远不变。
-
-
令牌桶算法(Token Bucket):
-
原理:系统以恒定速率往桶里放令牌,请求必须拿到令牌才能执行。
-
优点:允许一定程度的突发流量(只要桶里有存量令牌)。Guava 的 RateLimiter 就是典型的令牌桶实现。
-
2. 限流的架构分层
在实际工程中,限流通常部署在多个位置:
A. 网关层限流(入口保护)
-
工具:Nginx (limit_req), Spring Cloud Gateway (RequestRateLimiter)。
-
目的:阻断非法攻击或超过系统总容量的流量。通常配合 Redis 实现分布式限流。
B. 应用层限流(核心业务保护)
-
工具:Sentinel (阿里开源), Resilience4j (Hystrix 的替代者)。
-
目的:针对具体的接口(API)进行限流。比如“下单”接口和“查询”接口的限流阈值肯定不同。
C. 资源层限流(数据库/连接池)
-
方式:通过线程池隔离或连接池大小(如 HikariCP)来限制并发数,防止数据库被拖垮。
3. 分布式限流的挑战:Redis + Lua
单机限流(如 Guava)在微服务集群下是没用的,因为每个节点的计数器不共享。
-
方案:将限流计数器存在 Redis 中。
-
关键点:必须使用 Lua 脚本。因为限流涉及“读取-判断-写入”三个步骤,必须保证其原子性,否则在高并发下计数器会由于竞态条件而失效。
4. 资深开发的工程建议:限流后的“降级策略”
限流不是目的,保障可用性才是。当触发限流时,你应该提供以下处理方式:
-
快速失败(Default):返回
429 Too Many Requests。 -
排队等待:让请求进入队列慢慢处理(适合削峰填谷)。
-
服务降级:返回兜底数据。比如查询用户信息被限流了,可以返回一个缓存中的旧数据。
-
引导至静态页:比如抢购失败,跳转到一个“系统繁忙,请稍后再试”的静态 HTML。
📉 状态同步
-
2026-03-30:已完成限流算法、分层架构及分布式限流实现方案的系统梳理。
限流思维在职业转型中也非常有用。比如在做产品设计时,如何设计用户的操作频率限制以防止被爬虫抓取,这其实就是业务层的限流。
既然聊到了 Sentinel 这种限流工具,你想看看如何通过 Sentinel 控制台,在不重启 Java 应用的情况下实时调整限流阈值吗?