负载均衡负责集群维度的粗粒度流量兜底,网关负责接口、用户、参数级别的细粒度精准控制,两者配合而非替代。负载均衡对连接和转发层面的信息最敏感,网关对业务语义最了解,细粒度限流只适合在网关层做,硬塞给负载均衡会拖垮转发性能,也拿不到业务需要的特征维度。
网关限流和负载均衡限流区别在哪
这是架构设计中最高频的纠结点,很多团队在流量上涨后,第一反应是压榨负载均衡的限流能力,结果发现要么限不精准,要么误伤严重。
两者的数据源和统计粒度完全不同
负载均衡看到的是一张”流量进出表”来源IP、目标端口、连接数、QPS,网关看到的是完整的HTTP请求上下文URL路径、Header、Cookie、用户ID、请求体里的业务参数,这就是根本差异:
- 维度差异:负载均衡能按IP和端口限流,网关能按用户、接口、甚至某个商品ID限流
- 统计单位差异:负载均衡处理的是连接和请求,网关处理的是业务语义,同一类请求在网关层面可以聚合出更细的规则
- 时效性差异:负载均衡要尽量保持转发速度,不适合跑复杂的计数逻辑,网关本身就在业务链路里,多一层规则判断成本可被接受
典型的错误认知:Nginx限流等于细粒度限流
不少团队用Nginx的limit_req_zone做限流,觉得加个$request_uri变量就是细粒度了,这属于把限流粒度误当成细粒度,业内专家指出,按URI维度限流确实比全局限流前进了一步,但离真正的细粒度还差两层:
- 它统计的是请求次数,无法按用户身份聚合,同一个IP后面挂了一百个正常用户在共享额度时,只能一刀切
- Nginx限流模块的计数基于共享内存,多worker情况下是原子操作,在QPS过高的场景下,锁竞争的成本会侵蚀转发性能
网关的角色定位
网关(包括Spring Cloud Gateway、Kong、APISIX等)天然处于业务流量的汇聚点,既能读到请求全貌,又能把限流结果直接反馈给调用方,最合理的分工是:
| 控制面维度 | 承担者 | 核心指标 |
|---|---|---|
| 连接数兜底 | 负载均衡 | 活跃连接数、新建连接速率 |
| 单机粒度限流 | 负载均衡 | 基于IP的QPS粗限 |
| 接口级限流 | 网关 | 接口维度QPS、TPS |
| 用户级限流 | 网关 |
用户ID、AppKey维度配额 |
| 业务参数限流 | 网关 | 商品ID、地域、渠道等自定义维度 |
细粒度限流最佳实践落在哪一层
要落地到接口、用户、参数这种粒度,最佳实践是在网关层设置双层限流桶:外层走固定窗口或滑动窗口的快速通道,内层走令牌桶的精准通道。
第一层:快速失败的粗过滤
这一层放在网关最早期的filter链里,只做最粗的全局QPS拦截,判断逻辑简单到可以写成一行:
rate_limit: global_qps: 20000 window: 1s
超过阈值直接返回503,状态码自定义为429,让上游系统的重试策略能识别限流信号,这层的优势是极低的内存消耗和纳秒级别的判断延迟。
第二层:语义级的精准控制
需要读请求体、解析用户上下文,没法在前置filter做,典型的操作路径是:
- 网关解析JWT或Session,提取
userId和tenantId - 从Redis Cluster中读取该用户在当前时间窗口的已用配额,使用Lua脚本保证原子性
- 根据用户等级分配不同阈值,例如免费用户和付费用户分别走不同限流策略
- 若超限,写入一个带短TTL的block标记,后续请求直接被拦截
行业共识认为,这一层的核心前提是规则配置必须动态化,改限流阈值不能重启网关,否则每一次业务调整都意味着流量中断,首选配置中心推送(Nacos、Apollo),网关监听配置变更后,热更新本地规则缓存。
混合场景:多级限流策略的优先级
真实业务里,接口级限流和用户级限流会同时命中,比如一个秒杀活动,既要保证整体接口不被冲垮,又要限制单个用户反复刷单,此时策略优先级从高到低应该是:
- 参数级限流(白名单用户最高优先级,直接放行)
- 接口级限流(全局总量封顶)
- 用户级限流(单用户配额限制)
优先级判断做在网关规则引擎里,一条请求要过三个检查点,任何一个超限就立即拦截。网关的规则引擎建议使用规则脚本(如Lua)而非硬编码Java逻辑,这样调整策略时不用重新发布版本。
负载均衡的分工边界在哪
知道了核心最佳实践,还要明确负载均衡的边界,否则运维同学容易把配置加错地方。
负载均衡该管什么
无论用Nginx、LVS还是云上的SLB,它应该做的事情只有三件:
- 四层连接数限流:单IP的并发连接数,或者新建连接速率,防止连接耗尽
- 上游节点健康检查:每秒探活后端节点,异常节点直接摘除
- 集群入口的粗粒度QPS兜底:在全员限流还没生效的时候,先把最猛的那波流量拦一部分
这三件事都和IP、端口强相关,不需要解析业务数据,属于转发面的范畴。
负载均衡不该管什么
试图让负载均衡理解业务参数是大忌,具体场景如下:某电商平台做促销时,运营想把”只看床垫类目”的请求限流到每秒5000次,这个诉求放在网关,只需要一个API调用就能动态配置,但如果放在负载均衡层,则需要:
- 解析HTTP请求体
- 匹配商品类目关键字
- 维护类目维度的计数器
- 处理并发原子性问题
这一套流程下来,负载均衡的内存和CPU占用会明显上升,转发吞吐必然下降,北京一家头部电商公司的架构复盘显示,把这类限流逻辑从负载均衡迁到网关后,入口层的整体吞吐提升了一个量级。
边界划分的操作建议
- 采用LVS + Nginx + 微服务网关的三层结构,每层只管自己的事
- 负载均衡的限流阈值调得比网关宽松20%~30%,避免前端先拦截了网关想放行的请求
- 在监控面板上,把负载均衡拦截量和网关拦截量分开展示,便于判断流量缺口出现在哪一层
规则同步的落地路径
网关层做细粒度限流,还涉及一个复杂性课题网关集群的规则一致性。
本地缓存 + 异步刷新
所有网关节点在同一时刻用的是一份规则快照,配置中心推送新版本后,不是立即生效,而是先写入缓存,等下一个周期统一加载,这个延迟控制在几十毫秒到几百毫秒之间,可以接受。
分布式限流的Redis开销问题
细粒度限流最怕Redis被击穿,比如用户级限流,每秒几万个请求一次性打到Redis,很容易把单分片CPU打高,实操上分两步解决:
- 给Redis限流key加随机后缀,分到不同分片,分散热点
- 每个网关节点做秒级本地预判,连续N次超限的请求直接拦截,不再请求Redis,把回源率降低到可控范围
数据一致性兜底
Redis集群如果宕机,限流规则自动降级为每节点本地独立计数,虽然精确度下降,但能保证服务不被冲垮,上海一家金融科技公司的做法是,限流降级开关独立于主链路,任何中间件故障都优先保障业务可用性。
选型时的现实考量
团队在选方案的时候,除了架构合理性,还有几个绕不开的坑,提前知道能省不少钱。
价格和运维成本怎么权衡
纯开源方案(Nginx + APISIX + Redis)的软件成本为零,但运维投入偏高,需要一个能写Lua脚本的运维或开发,这类人才在一线城市的月薪成本不低,云上网关方案按QPS和API调用数计费,对中小团队更友好,就拿云上网关的细粒度限流功能来说,足够覆盖大部分场景,不用再单独搭Redis。统计显示,多数中小团队的成本上限在每月数千元,超过这个数字就会考虑自建,选型不必追求完美,匹配预算就好。
响应时间增长是否可接受
网格外的限流判断增加了1~3毫秒的延迟,这是可接受的代价,但前提是网关机器的CPU不能超卖,行业经验值是将网关CPU水位控制在60%以下,超了就先扩容再考虑优化逻辑。
埋点与可观测性
限流规则越细,排查问题越难,每个限流决策要打印出限流维度、规则ID、当前值、阈值、命中时间这五个要素,缺一不可,堆积在网关日志里,问题出现时能直接定位到是哪一个规则在拦流量。
一个合理的细粒度限流架构不是靠单一组件完成的,负载均衡把第一道闸门,网关做业务语义的精细控制,日请求量从百万级涨到亿级的过程中,前者的策略几乎不用变,后者则需要持续调整规则和配额,明确好这两者的分工,流量再涨心里也有底。
常见问题:细粒度限流怎么选型
Q:不用负载均衡的限流功能,会不会让后端暴露在突发流量下?不会,负载均衡的连接数兜底依然生效,它时刻在保护后端,细粒度限流的目的不是防御DDoS,而是保护业务资源比如某个接口的数据库连接池、某个用户的操作频率,两者不存在替代关系。
Q:Kubernetes Ingress Controller里的限流能力和网关限流是同一个层级吗?严格来说不是,Ingress Controller的限流本质是负载均衡的地址转换层限流,它的视角停留在Host和Path维度,如果业务有基于登录用户ID的限流需求,Ingress层拿不到JWT里的信息,限流自然无从谈起,K8s Ingress适合做集群级别的简单桶限流,而细粒度逻辑要放在Service Mesh或应用网关里。
Q:限流阈值应该设置成多少才合理?没有绝对数值,但有标准方法,先用容量压测得出单机支撑QPS,再乘以机器数,扣除20%的冗余,得到集群上限,接口级限流按这个基准配,用户级限流按用户群体分布来配,核心原则是,上限要留出人工干预的缓冲空间,全部跑满就失去了限流的意义。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/634088.html





