网关层怎么做限流才能既防攻击又不误伤正常用户
摘要:# 网关限流:别让“防贼”的墙,把自家客人也挡在门外 我前两天跟一个做电商的朋友吃饭,他跟我大倒苦水。说大促期间,为了防住羊毛党和恶意爬虫,技术团队把网关的限流阈值调得特别低。结果呢,攻击是防住了一些,但自家用户也崩了——页面疯狂报错,下单总失败,客服电…
网关限流:别让“防贼”的墙,把自家客人也挡在门外
我前两天跟一个做电商的朋友吃饭,他跟我大倒苦水。说大促期间,为了防住羊毛党和恶意爬虫,技术团队把网关的限流阈值调得特别低。结果呢,攻击是防住了一些,但自家用户也崩了——页面疯狂报错,下单总失败,客服电话被打爆。他苦笑着说:“这感觉,就像为了防小偷,把自家大门焊死了,结果自家人也进不来。”
这场景你应该不陌生吧?很多技术团队一提到网关限流,脑子里蹦出来的就是QPS(每秒查询率)、并发数这些硬邦邦的指标。但说实话,只盯着数字的限流,本质上是在“偷懒”。它把复杂的人机识别、业务逻辑,简化成了简单的数学题,误伤几乎是必然的。
今天咱们就聊聊,在网关这个流量总入口,怎么做限流,才能既精准地拦住“坏蛋”,又让“好人”一路畅通。
一、先搞明白:你的“敌人”和“客人”长什么样?
很多方案一上来就谈算法、谈配置,我觉得这是本末倒置。你得先想清楚,你要防的是什么,要保的又是什么。
- 敌人(攻击/异常流量): 这可不是一个整体。有低级的脚本小子搞的CC攻击(每秒几万次请求怼你一个接口);有高级点的,用代理IP池模拟真人行为的爬虫;还有更“聪明”的,专门盯着你业务逻辑漏洞,比如凌晨抢券、批量注册。
- 客人(正常用户): 也分三六九等。有闲逛的游客,有正在加购的潜在客户,有正在支付的关键用户。一个正在输支付密码的请求,和一个在浏览商品详情的请求,重要性能一样吗?
说白了,限流的本质不是“限制流量”,而是“区分流量”。你得分得清敌我,才能谈怎么打。
二、别只靠“单点阈值”:那玩意儿太糙了
我见过太多团队,网关限流就配一条规则:/api/* 路径,全局QPS 1000。这简直是“自杀式防护”。
- 问题在哪? 一个热门秒杀接口,可能瞬间需要5000的QPS;而一个后台管理接口,可能平时只有10的QPS。你用一把尺子去量所有东西,能准吗?
- 误伤怎么来的? 攻击者往往只盯着你一个接口猛打(比如登录接口)。一旦这个接口的流量达到全局阈值,网关会无差别地拒绝所有接口的后续请求。正常用户访问其他完全无关的页面,也会莫名其妙地失败。这冤不冤?
所以,第一原则:限流必须精细化到“维度”。
- 按接口限流: 这是最基本的。给
/api/login、/api/seckill分别设置不同的阈值。后台接口可以设低点,核心业务接口根据压测结果设高点。 - 按用户/客户端限流: 这就高级点了。通过用户ID、设备指纹或者API Key来区分。比如,一个正常用户每分钟请求登录接口不应超过5次,一个IP地址每小时注册次数不应超过3个。这才是精准打击。
- 按业务状态限流: 这是我个人非常推崇的。举个例子,对于未登录的游客,浏览商品的限流可以宽松;但对于已登录、购物车里有商品、尤其是进入了支付流程的用户,他们的请求优先级必须调到最高,甚至可以暂时豁免某些限流规则。你得保证“金主爸爸”的体验。
三、算法选择:别迷信“最牛”的,选最“合适”的
一说算法,就是令牌桶、漏桶、滑动窗口……技术博客里都讲烂了。我不重复那些公式,就说点实在的。
- 计数器固定窗口: 最简单,但问题最大。比如你设“每分钟100次”。如果攻击者在每分钟的最后1秒和下一分钟的第1秒,集中发起200次请求,会完美地绕过限制。别用它来做核心防护,太容易钻空子。
- 滑动窗口: 这是计数器算法的改良版,更平滑,能应对上面那种“窗口边界攻击”,是当前的主流选择。很多开源网关(像Spring Cloud Gateway、Nginx Plus)都内置了。
- 令牌桶/漏桶: 更适合做“流量整形”,让流量输出得更均匀平滑,防止系统被突发流量冲垮。比如,你希望无论上游来多少请求,下游服务每秒最多只处理1000个,用这个就对了。
我的建议是:组合使用。 在网关上,用滑动窗口算法按用户/IP做精细化的防暴刷限流;在核心服务入口,再用令牌桶做一层总的流量整形,保服务不宕机。
四、动态调整与熔断:让限流“活”起来
静态配置的限流,在瞬息万变的线上环境里,就是个“铁憨憨”。真正的防护,得有弹性。
- 动态阈值: 根据系统实时负载自动调整。比如,当CPU使用率超过80%时,自动将非核心接口的限流阈值调低20%,优先保障核心交易链路。等负载降下来,再自动恢复。
- 与熔断器联动: 这是很多方案会忽略的一点。如果某个服务(比如用户积分服务)已经响应超时或失败,熔断器会把它“掐断”。这时候,网关应该能感知到,并立即对调用这个服务的所有上游请求,进行更严格的限流甚至快速失败。这叫“上游保护”,防止垃圾流量继续堆积,把整个链路拖死。
- 慢启动(Warm Up): 对于刚重启或扩容的服务实例,别一下子把流量全打过去。限流规则可以设置一个“预热时间”,在几分钟内,从低阈值慢慢增加到正常阈值,给JVM、连接池一个热身的机会。
五、用户体验:被限了,也得给个“体面的告别”
这一点,技术人特别容易忽略。“啪”一下给用户返回个 429 Too Many Requests 或者更糟的 500 Internal Server Error,用户只会觉得:这破App又崩了!
- 友好的提示: 对于疑似正常用户的请求(比如因为操作太快被限),返回一个清晰的JSON或HTML页面:“您操作得太频繁啦,请稍等5秒再试试哦~”。这比冷冰冰的错误码好一万倍。
- 差异化处理: 对于明确是恶意IP(比如来自已知攻击IP库)的请求,直接快速失败,甚至返回假数据消耗对方资源。对于普通IP,可以引入“排队”或“延迟响应”机制。
- 客户端配合: 在App或网页端,收到限流提示后,可以自动禁用按钮几秒钟,并显示友好的倒计时,引导用户正确操作。
六、别忘了监控与告警:限流不是“配完就拉倒”
你配了限流,怎么知道它生没生效?有没有误伤?攻击有没有变种?
- 必须监控的关键指标:
- 每个限流规则的拦截请求数和放行请求数。
- 被拦截请求的用户ID/IP/接口分布(看看误伤了谁)。
- 系统整体的成功率和延迟(限流后,服务是不是更稳了)。
- 设置智能告警: 不要只盯着“拦截数高”就报警。要关注“在核心接口上,来自正常用户特征IP的拦截率突然飙升”。这很可能就是误伤开始了,或者你的规则该调整了。
写在最后
网关限流,绝不是在控制台上填几个数字那么简单。它是一项融合了业务理解、算法选型、动态策略和用户体验的综合工程。
最怕的,就是技术团队为了“安全”的KPI,制定出过于严苛的限流策略。表面上,攻击请求进不来了,报表好看了;实际上,正常业务也在默默流血,用户流失你都不知道怎么流的。
所以,下次再配置限流规则时,不妨多问自己一句:“我这一条规则下去,会挡住我的真实用户吗?”
多想想,多看看数据,让防护的“墙”变得智能而通透。毕竟,我们的目标从来不是砌一堵密不透风的墙,而是装上一扇能自动识别来客的、聪明的“门”。
行了,关于限流,就先聊这么多。如果你源站的关键接口还只靠一个全局QPS硬扛,心里应该已经有答案了吧?

