本文目录导读:

高频请求攻击(如CC攻击、DDoS攻击)的核心是短时间内发送远超服务器处理能力的请求,限流是应对这类攻击最有效的手段之一,以下是几种主流的限流策略及其实现方式,按从简单到复杂、从单机到分布式的顺序排列:
单机限流(针对单台服务器)
这些方法适用于单机部署,或者在分布式系统中作为第一道防线。
-
计数器法(固定窗口)
- 原理:将时间划分为固定窗口(如1秒),每个窗口内维护一个计数器,超过阈值则拒绝请求。
- 缺点:存在“临界突变”问题,例如窗口为1秒,阈值100,如果在0.99秒和1.01秒各发送100个请求,系统会在0.001秒内承受200个请求,可能被冲垮。
- 实现:使用
AtomicInteger+System.currentTimeMillis()/ 时间窗口取模。
-
滑动窗口日志法
- 原理:记录每次请求的时间戳,统计最近一个时间窗口内的请求数。
- 优点:解决了固定窗口的临界问题。
- 缺点:需要存储大量时间戳,内存消耗较大。
- 实现:使用 Redis 的 Sorted Set(ZSet),以时间戳作为 score,通过
ZREMRANGEBYSCORE删除过期记录,再用ZCARD统计数量。
-
令牌桶算法
- 原理:以恒定速率向桶中添加令牌,请求需消耗一个令牌才能通过,桶有容量上限(应对突发流量)。
- 优点:允许一定程度的突发请求,且能平滑整体请求速率。
- 实现:
- 单机:Google Guava
RateLimiter。 - 分布式:Redis 实现(
get+set或 Lua 脚本)。
- 单机:Google Guava
-
漏桶算法
- 原理:一个固定容量的桶,请求以任意速率流入,以固定速率流出(处理),若桶满,则请求被丢弃。
- 优点:强制将请求速率稳定在固定值,能有效应对突发流量(直接丢弃超出的部分),非常适合保护下游系统。
- 实现:Nginx
limit_req模块默认使用漏桶算法。
分布式限流(针对集群/微服务)
当服务部署在多台服务器时,单机限流会导致总吞吐量不准确,需要集中式存储。
-
基于 Redis 的滑动窗口(推荐)
-
方案:结合 Redis 的 Sorted Set(有序集合)和时间戳,实现精确的分布式滑动窗口限流。
-
伪代码思想:
-- Lua脚本 (保证原子性) local key = KEYS[1] local now = tonumber(ARGV[1]) local window = tonumber(ARGV[2]) -- 窗口大小,如1000毫秒 local limit = tonumber(ARGV[3]) -- 阈值 -- 移除窗口之外的所有元素 redis.call('ZREMRANGEBYSCORE', key, 0, now - window) -- 获取当前窗口内请求数量 local current = redis.call('ZCARD', key) if current >= limit then return 0 -- 限流 else redis.call('ZADD', key, now, now) -- 加入当前请求 redis.call('PEXPIRE', key, window) -- 设置过期时间 return 1 -- 放行 end
-
-
基于 Redis 的令牌桶
- 方案:使用 Redis 的
GET、SET或 Lua 脚本维护令牌数量和时间差,计算应补充的令牌。 - 注意:需要处理 Redis 单点故障,可用哨兵或集群模式。
- 方案:使用 Redis 的
-
网关层限流(推荐)
- 方案:在流量进入微服务集群之前进行统一限流。
- 工具:Nginx +
limit_req模块(基于漏桶)、OpenResty(Lua 脚本实现灵活的限流策略)、Spring Cloud Gateway/Zuul(配合 Redis 实现分布式限流)、Kong、Envoy等 API 网关。
高级综合防御策略
面对大规模高频攻击(如CC攻击),单靠限流可能不够,需要组合拳。
-
熔断与降级
- 原理:当错误率或响应时间达到阈值时,直接切断对后端的调用,返回预设的回应(如“系统繁忙”)。
- 工具:Hystrix(Netflix,已维护模式)、Resilience4j(推荐,Java)、Sentinel(阿里,功能强大,支持多种限流和熔断策略)。
-
用户/IP 分级限流
- 策略:
- VIP用户:限流阈值高。
- 普通用户:限流阈值低。
- 非登录用户:限流阈值极低或直接拒绝高频访问。
- 实现:请求头中提取用户ID或Token,结合Redis计数器。
- 策略:
-
验证码与黑名单
- 验证码:当连续失败次数或请求频率超过低阈值时,强制要求输入验证码(图片、滑块、行为验证码)。
- 动态黑名单:自动将触达限流阈值且判断为恶意(如访问不存在的URL、无Referer、User-Agent异常)的IP或用户加入黑名单(本地或Redis),一段时间内拒绝所有请求。
-
AI/行为分析
- 原理:分析用户的行为特征(如鼠标轨迹、点击间隔、页面浏览模式),识别出非人类的爬虫或攻击程序,需要引入机器学习或规则引擎。
部署与配置建议
-
多层防护:
- 外网入口:CDN + WAF(Web应用防火墙,可封杀IP和特征)。
- 负载均衡/网关:Nginx
limit_req或网关限流。 - 业务层:Redis分布式限流 + 熔断降级。
-
参数配置原则:
- 超时机制:设置合理的请求超时时间(如500ms),避免请求堆积。
- 拒绝策略:返回友好的错误码(如
429 Too Many Requests),并在Response Header中加入Retry-After。 - 动态调整:限流阈值不应写死,应支持通过配置中心(如 Nacos、Apollo)动态调整,以应对突发的正常流量(如秒杀)。
应对高频攻击的推荐路线
- 第一步(最低成本):在 Nginx 上启用
limit_req(漏桶算法)和limit_conn(限制连接数),这是最直接、最有效的“止血”手段。 - 第二步(日常防护):在服务网关 (如Gateway/Nginx Lua) 或业务代码中,使用 Redis 滑动窗口 实现针对用户/IP的分布式限流。
- 第三步(复杂场景):引入 Sentinel 或 Resilience4j 实现熔断、降级、热点参数限流。
- 第四步(终极手段):配合 WAF、CDN、行为验证码 和 动态IP黑名单 进行立体防御。