微服务限流实战

一、业务场景:什么情况下必须限流?

1. 突发流量场景(秒杀 / 抢购)
复制代码
活动期 QPS = 2000日常 QPS = 10-50→ 突发 40 倍流量,必须限流

项目实战

"季度结息活动凌晨 0 点开放 ------QPS 从 50 飙到 3000 ------没有限流系统就崩了。"

2. 恶意攻击防护
复制代码
恶意 IP 疯狂请求 → 限流保护压测得到系统最大 QPS → 设上限

"系统压测最大 QPS = 1500 ------限流阈值设 1200 ------保留 20% 缓冲给突发流量。"

二、Nginx 限流(2 大经典场景)

1. 控制速率(漏桶算法)

应对突发流量 --- 让请求以固定速率处理

复制代码
# nginx.confhttp {    # 定义限流区域:10MB 内存,每秒 1 个请求    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;        server {        location /api/ {            # ⚠️ burst=5 允许突发 5 个请求,nodelay 不延迟立即处理            limit_req zone=one burst=5 nodelay;            proxy_pass http://backend;        }    }}

关键参数

  • rate=1r/s = 每秒 1 个请求
  • burst=5 = 允许突发 5 个漏桶缓冲
  • nodelay = 突发请求立即处理不排队

Mavis 实战注释

  • ⚠️ $binary_remote_addr = 按 IP 限流
  • ⚠️ zone=one:10m = 10MB 内存够记 16 万 IP
2. 控制并发数
复制代码
http {    # 限制每个 IP 并发连接数 = 10    limit_conn_zone $binary_remote_addr zone=addr:10m;        server {        location /api/ {            limit_conn addr 10;            proxy_pass http://backend;        }    }}

"limit_req 控制速率,limit_conn 控制并发数"

三、网关限流(Spring Cloud Gateway + Sentinel)

1. 核心配置
复制代码
# application.ymlspring:  cloud:    gateway:      routes:        - id: limit_route          uri: lb://backend-service          predicates:            - Path=/api/**          filters:            # ⚠️ 令牌桶算法,每秒填充 100 个,桶容量 200            - name: RequestRateLimiter              args:                redis-rate-limiter.replenishRate: 100    # ⚠️ 每秒填充速率                redis-rate-limiter.burstCapacity: 200    # ⚠️ 令牌桶总容量                key-resolver: "#{@ipKeyResolver}"        # ⚠️ 按 IP 限流
2. KeyResolver 配置(按 IP 或路径)
复制代码
@Configurationpublic class RateLimiterConfig {    @Bean    public KeyResolver ipKeyResolver() {        return exchange -> Mono.just(            exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()        );    }        @Bean    public KeyResolver pathKeyResolver() {        return exchange -> Mono.just(            exchange.getRequest().getPath().value()        );    }}

"按 IP 限流防恶意攻击按路径限流保护热点接口 ------两个 KeyResolver 配合用。"

四、限流 4 大经典算法

1. 固定窗口计数器最简单
复制代码
时间窗口:1 秒限流阈值:100 QPS第 1 秒:请求 1-100 通过,第 101 个拒绝第 2 秒:计数器清零,重新开始

优点 :实现简单 缺点窗口边界突刺1 秒末 + 2 秒初 = 200 QPS超阈值 2 倍

2. 滑动窗口计数器改进版
复制代码
把 1 秒分成 5 个 200ms 小窗口每个小窗口独立计数总请求 = 最近 5 个小窗口之和

优点平滑限流避免边界突刺 缺点窗口越多,内存越大

3. 漏桶算法Nginx 用这个
复制代码
请求 → 漏桶 → 处理(固定速率)       ↓       桶满 → 拒绝

特点强制恒定速率处理 ------保护下游 ------适合流量整形

Mavis 注解

  • ⚠️ 漏桶 = "整流" ------ 流量再大,出去也是匀速
  • ⚠️ 适合保护下游系统 ------不能让下游被打挂
4. 令牌桶算法Spring Cloud Gateway 用这个
复制代码
令牌桶 → 匀速生成令牌 → 请求拿令牌 → 处理                  ↓              桶满 → 丢弃令牌

特点允许突发流量 ------桶里存多少就能突多少

Mavis 注解

  • ⚠️ 令牌桶 = "蓄洪" ------ 平时攒令牌,大流量来了能扛一阵
  • ⚠️ 秒杀 / 抢购 首选------应对突发
5. 4 大算法对比表
算法 原理 优点 缺点 适用
固定窗口 1 个大窗口计数 实现简单 边界突刺 不推荐生产
滑动窗口 N 个小窗口求和 平滑 内存占用 金融首选
漏桶 匀速处理 保护下游 无法应对突发 流量整形
令牌桶 匀速生成令牌 可突发 实现复杂 秒杀抢购

记忆口诀

"漏桶整流,令牌蓄洪" "固定窗口有边界突刺,滑动窗口平滑" "秒杀用令牌,金融用滑动"

五、3 大经典面试追问

追问 1:为什么用令牌桶不用漏桶?

"秒杀场景允许突发 ------令牌桶攒令牌能扛突发流量漏桶强制匀速 ------秒杀高峰用户体验差。"

追问 2:限流阈值怎么定?

"压测得到系统最大 QPS = 1500限流阈值设 1200 ------保留 20% 缓冲 ------给 GC / 网络抖动留余量。"

追问 3:网关限流和 Nginx 限流什么区别?

"Nginx 限流在最外层 ------防大流量直接打挂网关网关限流在业务层 ------按用户 / IP / 路径细粒度控制两层配合用 ------Nginx 先挡 80% 恶意流量网关再细控业务。"

六、记忆口诀

"秒杀令牌,流量整形漏桶"

"Nginx 外层挡恶意流量,网关内层细控"

"limit_req 速率,limit_conn 并发"

"令牌桶 replenishRate + burstCapacity"

"QPS = 1500 时限流设 1200,留 20% 缓冲"

"滑动窗口防边界突刺,金融首选"
"高并发限流体系建设"

  • 双层限流Nginx(最外层)+ Spring Cloud Gateway + Sentinel(业务层)
  • 算法选型令牌桶(应对突发)+ 滑动窗口(金融合规)
  • 实战季度结息 QPS 从 50 飙到 3000限流后系统稳定
  • 配置replenishRate=100 + burstCapacity=200保留 20% 缓冲
  • 按 IP + 路径双维度限流防恶意攻击 + 保护热点接口