微服务限流实战:Nginx 漏桶与网关令牌桶

限流不是为了让系统"变慢",而是为了让系统在突发流量、恶意请求或超过承载能力时,仍然能保住核心服务。

一句话概括:限流是在入口处控制请求速度或并发数量,Nginx 常用漏桶算法控制请求流出速率,Spring Cloud Gateway 常用令牌桶算法决定请求是否允许通过。


外部请求
入口限流
Tomcat

最大连接数
Nginx

漏桶限速
Nginx

连接数限制
Gateway

令牌桶限流
自定义拦截器
请求按固定速率进入后端
拿到令牌才允许通过

为什么要限流

项目中做限流一般有两个原因:

  1. 业务确实有突发流量:比如优惠券抢购,平时 QPS 只有 10 到 50,活动时瞬间到 2000。
  2. 防止恶意刷接口:比如登录、短信、下单、支付等接口被频繁请求。

面试回答时最好带具体业务场景,不要只说"为了保护系统"。

Nginx 漏桶限流

漏桶算法可以想成一个桶:

  • 请求像水一样进入桶。
  • 桶按固定速率漏水。
  • 后端按固定速率处理请求。
  • 桶满后,多余请求等待或被丢弃。

未满
已满
突发请求进入
漏桶缓存请求
桶是否已满
请求进入桶中等待
请求被拒绝或延迟
按固定速率漏出
后端服务稳定处理

Nginx 常见配置思路:

nginx 复制代码
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;

location /api/ {
    limit_req zone=perip burst=20 nodelay;
}

几个参数要能说清楚:

参数 含义
key 限流对象,比如客户端 IP
zone 共享存储区,用来保存访问状态
rate 最大访问速率,比如 10r/s
burst 突发请求容量,相当于桶大小
nodelay 不排队等待,尽快处理或拒绝

rateburstnodelay 怎么直观理解

假设配置是:

nginx 复制代码
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;

location /api/ {
    limit_req zone=perip burst=20 nodelay;
}

可以这样理解:

  • rate=10r/s:稳定情况下,每秒最多按 10 个请求的速度处理。
  • burst=20:允许额外暂存 20 个突发请求。
  • 没有 nodelay:突发请求会排队,按 10r/s 慢慢放行。
  • nodelay:突发请求不排队等待,会尽快处理;超过 burst 的请求直接被限流。



瞬间进来 35 个请求
10 个按速率正常处理
20 个进入 burst 突发容量
是否配置 nodelay
排队等待

按固定速率放行
尽快处理突发请求
超过容量的 5 个请求
被拒绝或返回限流响应

这个例子比单纯背参数更好用。面试时只要说出"稳定速率 + 突发容量 + 是否排队",就基本讲清楚了。

Nginx 并发连接数限制

除了控制请求速率,Nginx 也能限制连接数:

nginx 复制代码
limit_conn perip 20;
limit_conn perserver 100;

含义:

  • perip 20:单个 IP 最多同时保持 20 个连接。
  • perserver 100:当前虚拟主机最多处理 100 个并发连接。

速率限制解决"请求来得太快",连接数限制解决"连接占用太多"。

Gateway 令牌桶限流

令牌桶算法的逻辑和漏桶不一样:

  • 系统按固定速率生成令牌。
  • 令牌放入令牌桶。
  • 桶满后暂停生成。
  • 请求必须先拿到令牌。
  • 没有令牌的请求会被阻塞或拒绝。



令牌生成器
按固定速率

生成令牌
令牌桶
请求进入网关
是否拿到令牌
请求放行
请求被限流

Spring Cloud Gateway 可以通过 RequestRateLimiter 做局部过滤器限流:

参数 含义
key-resolver 定义限流对象,比如 IP、路径、用户 ID
replenishRate 每秒填充令牌的平均速率
burstCapacity 令牌桶总容量

漏桶和令牌桶怎么选

对比点 漏桶算法 令牌桶算法
核心思想 请求按固定速率流出 拿到令牌才放行
突发流量 更平滑,削峰明显 支持一定突发能力
常见位置 Nginx Gateway
适合场景 控制后端稳定处理速率 允许短时间突发但限制总体速率

面试回答模板

可以这样答:

我们项目在活动接口上做过限流。平时 QPS 大概几十,活动高峰可能到 2000,为了防止突发流量打垮系统,在入口层做了限流。Nginx 侧用漏桶算法控制请求速率,让请求以固定速率进入后端,也可以限制单 IP 连接数。网关侧可以使用 Spring Cloud Gateway 的 RequestRateLimiter,底层是令牌桶算法,通过 key-resolver 指定限流对象,比如 IP 或路径,通过 replenishRateburstCapacity 控制令牌生成速率和桶容量。

小结

限流要讲业务背景,也要讲算法差异:

漏桶更强调平滑流出,令牌桶更强调拿令牌放行并允许一定突发。

项目回答里带上 QPS、限流位置和参数,比只背算法更像真实经验。

相关推荐
Dicky-_-zhang8 小时前
微服务安全防护实战:OAuth2与JWT鉴权
java·jvm
牙牙学语的阿猿9 小时前
sentinel创建规则时的坑
java·开发语言·sentinel
罗超驿9 小时前
1.JavaEE初阶学习安排+介绍计算机是如何工作的
java·学习·java-ee
超梦dasgg9 小时前
Java 生产环境 JVM 调优实战
java·开发语言·jvm
phltxy9 小时前
RabbitMQ 工作模式与Java原生客户端案例
java·rabbitmq·java-rabbitmq
努力发光的程序员9 小时前
互联网大厂Java面试问答及技术分析(涵盖Spring Boot及微服务)
java·微服务·面试·springboot·技术问答
装不满的克莱因瓶9 小时前
【项目亮点四】支付订单超时处理与状态补偿机制设计
java·开发语言·后端·rabbitmq·消息中间件
@Murphy9 小时前
java 面试
java·开发语言·面试
bug-100869 小时前
为什么history模式默认会请求后端资源?
前端·vue.js·nginx