Composer 本身不提供限流能力,限流需配置在前端网关层:Nginx Ingress 通过 annotation(如 rate-limit-rps)和预声明 zone 的 configuration-snippet 实现;Envoy Gateway 需部署 RateLimitService 并在 HTTPRoute 中启用 filter;健康检查需主动探测与细粒度校验;burst+nodelay 组合需用恒定 RPS 压测验证。

Composer 调度网关本身不直接提供限流能力——它不是网关组件,而是 PHP 的依赖管理工具。你真正要配限流的,是运行在 Composer 所部署服务前端的网关层,比如 Nginx、Envoy 或 Kubernetes Ingress Controller(如 nginx-ingress)。下面按真实生产链路拆解关键配置点。
nginx-ingress 中用 annotation 配 rate-limit-connections 和 rate-limit-rps
如果你用的是 nginx-ingress-controller,限流必须通过 Ingress 资源的 annotation 控制,而不是改 Nginx 主配置。这些 annotation 会由控制器翻译成底层 Nginx 指令。
-
nginx.ingress.kubernetes.io/rate-limit-connections:限制单个 IP 并发连接数,适合防慢速攻击或连接耗尽 -
nginx.ingress.kubernetes.io/rate-limit-rps:限制每秒请求数(Requests Per Second),注意它基于$binary_remote_addr,对代理环境需确认X-Forwarded-For是否被正确传递 - 两者可共存,但
rate-limit-rps默认 burst=10 且无nodelay,突发流量会被延迟排队;若要允许短时突增,得配合nginx.ingress.kubernetes.io/configuration-snippet注入原始 limit_req 指令
示例片段:
annotations:
nginx.ingress.kubernetes.io/rate-limit-connections: "50"
nginx.ingress.kubernetes.io/rate-limit-rps: "100"
nginx.ingress.kubernetes.io/configuration-snippet: |
limit_req zone=myapi burst=200 nodelay;
⚠️ 注意:configuration-snippet 中定义的 zone 必须已在 ingress-controller 的 ConfigMap 里预声明(通过 limit-req-zone 字段),否则 reload 失败。
Envoy Gateway 中用 RateLimitService 做分布式限流
Envoy Gateway(EG)原生支持 RateLimitService(RLS)协议,适合跨多实例做全局统一限流。它不依赖本地内存计数,而是把决策委托给独立的限流服务(如 Lyft 开源的 envoy-ratelimit)。
- 必须部署一个 RLS server,并在 EG 的
EnvoyProxyCRD 中配置rateLimitService地址 - 限流策略写在
HTTPRoute的filters下,用ExtensionRef引用自定义限流配置 - RLS 返回状态码为
429时,EG 默认透传,不会自动加Retry-After,需在 RLS 侧显式返回该 header
典型错误:只配了 RLS 地址但没在 HTTPRoute 中启用 filter,限流完全不生效;或者 RLS server 响应超时,EG 默认放行(fail-open),反而失去保护。
负载高时 upstream health_check 不只是“探测存活”
单纯靠 max_fails/fail_timeout 做被动摘除,在高负载下反应太慢。Nginx 的 health_check 指令(需在 upstream 块内)支持主动周期探测 + 状态码/响应体匹配,但要注意:
- 健康检查请求默认不带
Host头,后端若校验 Host 可能全失败,得用health_check_http_version 1.1+health_check_header Host example.com -
health_check和proxy_pass共享 connection pool,高并发下健康检查可能抢走连接资源,建议设health_check_requests 1控制并发探测数 - Kubernetes Ingress 场景下,
nginx.ingress.kubernetes.io/health-check-pathannotation 更常用,但它只影响/healthz类路径,无法做细粒度响应内容校验
真正压测时你会发现:后端响应时间从 50ms 涨到 800ms,但连接还没被标记为 fail——这时得结合 least_time 或 least_conn 算法,而非只看存活。
burst 和 nodelay 组合容易误判“限流没起作用”
很多人看到 limit_req zone=foo burst=50 nodelay 配置后,用 ab 或 wrk 压测发现前 50 个请求都成功了,就以为限流失效。其实这是预期行为:
-
burst是令牌桶的“容量”,nodelay表示不排队、直接拒绝超限请求 - 但 Nginx 的实现里,burst 容量是按“请求到达时刻”动态填充的,只要请求间隔大于 1/rate,桶就会恢复空位
- 所以连续 50 个请求打进来,只要它们在 1 秒内到达,全部进 burst;第 51 个才 503;但如果第 51 个隔了 200ms 才来,桶已补回 2 个 token,它就能过
验证是否生效,别用短脉冲压测,改用恒定 RPS(如 wrk -R 120),观察 429 比例是否稳定在 20% 左右(假设 rate=100r/s)。否则你调的只是“突发缓冲区大小”,不是“速率上限”。


















