Nginx、HAProxy与Envoy生产流量治理及故障排查
反向代理和负载均衡位于请求入口,一处错误可能影响全部用户。生产问题常表现为 502、503、504、连接重置、长连接中断、单后端过载或重试风暴。本文从请求路径、超时、连接池、健康检查、TLS、限流和可观测性出发,建立 Nginx、HAProxy 与 Envoy 的通用治理方法。
一、先画出完整请求路径
客户端
↓ DNS/CDN/WAF
公网或专线负载均衡
↓
Nginx / HAProxy / Envoy
↓
应用网关或服务
↓
数据库、缓存、第三方依赖
排障必须知道错误由哪一层生成。相同的 504 可能来自 CDN 等待入口、代理等待上游,或应用等待数据库。
每层记录:
- 连接与响应超时;
- 重试次数和条件;
- 最大请求/响应大小;
- TLS 终止位置;
- 客户端真实 IP 传递;
- 健康检查方式;
- 连接复用和空闲时间;
- 日志中的 request ID。
二、工具定位
Nginx
适合 Web 反向代理、静态资源、TLS 终止、缓存、限流和较简单的四/七层代理。配置清晰,生态成熟。
HAProxy
适合高性能四/七层负载均衡,统计和健康检查能力强,后端状态控制细致。
Envoy
动态配置、HTTP/2、gRPC、细粒度指标、重试/熔断和服务网格能力强,但配置和运行复杂度更高。
选择工具时比较协议、动态发现、配置变更方式、运维能力和可观测性,而不是只看基准测试吞吐。
三、超时预算
超时必须沿调用链递减,外层应略大于内层加上重试预算。
用户总超时 10s
入口代理 9s
应用处理 7s
下游调用 2s × 最多2次
数据库语句 1.5s
关键超时:
- 建立连接超时;
- 发送请求超时;
- 首字节/读取超时;
- 写响应超时;
- 空闲连接超时;
- gRPC deadline;
- WebSocket 长连接空闲时间。
过短会误杀正常请求,过长会让故障请求占满连接、线程和内存。必须结合业务 SLO 和下游容量设置。
四、理解常见状态码
| 状态 | 常见方向 |
|---|---|
| 400 | 请求格式、Host、Header 或协议异常 |
| 401/403 | 认证、授权、WAF/ACL |
| 408 | 请求超时 |
| 413 | 请求体超过限制 |
| 429 | 限流或过载保护 |
| 499 | Nginx记录客户端提前断开 |
| 502 | 上游连接失败、重置或响应非法 |
| 503 | 无健康后端、熔断、主动拒绝 |
| 504 | 等待上游响应超时 |
错误码必须与代理错误日志、上游应用日志和同一 request ID 关联。
五、连接复用与端口
代理到上游若每次新建 TCP/TLS 连接,会增加延迟并消耗临时端口。启用 keepalive 时又需确保连接池、空闲超时和后端关闭行为一致。
ss -s
ss -tan state time-wait | wc -l
ss -tan state syn-sent | wc -l
cat /proc/sys/net/ipv4/ip_local_port_range
注意:
- Nginx upstream keepalive 是每 worker 的空闲连接缓存;
- HTTP/1.1 需正确清理
Connection头; - HTTP/2 多路复用改变连接数量和故障影响;
- NAT/SNAT 层也可能端口耗尽;
- 后端 idle timeout 短于代理时,会复用到已关闭连接。
六、负载均衡算法
常见算法:轮询、最少连接、加权、源地址哈希、一致性哈希、随机二选一。
选择依据:
- 请求耗时是否差异很大;
- 节点容量是否一致;
- 是否需要会话粘滞;
- 缓存命中是否依赖 Key;
- 长连接数量是否均匀;
- 扩缩容时是否允许大量映射变化。
粘滞会话可能造成热点和故障恢复困难。能在应用层共享会话时,通常优先无状态化。
七、健康检查
TCP 端口可连接不代表业务健康。HTTP 检查应验证关键依赖,但也不能过重,以免健康检查本身压垮系统。
设计:
- liveness:进程是否应被重启;
- readiness:是否可以接收新流量;
- startup:慢启动期间避免过早判断失败;
- 深度业务检查:用于监控,不一定直接摘除节点。
设置连续成功/失败阈值、检查间隔和慢启动,避免节点在临界状态反复加入和摘除。
八、重试、熔断与过载保护
重试会放大流量。若三层各重试两次,一次用户请求可能产生多次下游请求。
只对明确可重试、幂等且剩余超时足够的错误重试。POST、支付和创建类请求必须通过幂等键或业务语义保证安全。
保护手段:
- 最大并发和排队上限;
- 连接池上限;
- 每客户端/令牌/接口限流;
- 熔断器;
- 异常节点摘除;
- 负载丢弃;
- 慢启动;
- 重试预算。
过载时快速返回 429/503 往往比让所有请求等待到 504 更容易恢复。
九、Nginx关键实践
upstream app_backend {
zone app_backend 64k;
least_conn;
server 10.0.0.11:8080 max_fails=3 fail_timeout=10s;
server 10.0.0.12:8080 max_fails=3 fail_timeout=10s;
keepalive 64;
}
server {
location / {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Request-ID $request_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 2s;
proxy_read_timeout 15s;
proxy_pass http://app_backend;
}
}
上线前:
nginx -t
nginx -T > /secure-path/nginx-expanded.conf
nginx -s reload
平滑重载会启动新 worker 并让旧 worker 退出,但长连接和错误配置仍可能延长退出。应监控旧 worker 数量和内存。
十、HAProxy关键实践
HAProxy 配置应包含合理的 connect/client/server timeout、健康检查、日志格式和统计接口。check 只做 TCP 检查时可能无法发现应用逻辑错误,可按接口增加 HTTP 检查。
运行时 API 可查看和调整后端状态,但操作必须审计。配置发布前使用:
haproxy -c -f /etc/haproxy/haproxy.cfg
利用 seamless reload 时仍需观察旧进程、监听 socket、连接迁移和配置兼容。
十一、Envoy关键实践
Envoy 通过 cluster、listener、route、endpoint 和 filter 组织配置。生产关注:
- xDS 控制面可用性和最后有效配置;
- endpoint 健康与 panic threshold;
- circuit breaker 和 outlier detection;
- request timeout、per-try timeout 与 retry policy;
- HTTP/2、gRPC 和流式请求;
- admin 接口访问控制;
- 配置热更新和版本回退。
不要把 Envoy admin 端口暴露给不可信网络,它可泄露拓扑、配置和指标。
十二、TLS与证书
检查:
- 证书链、SAN、有效期和密钥匹配;
- TLS 最低版本和密码套件;
- OCSP stapling;
- SNI 多证书;
- 双向 TLS 的信任链和吊销;
- 会话复用;
- 证书轮换是否需要重载;
- 上游 TLS 的主机名验证。
openssl s_client -connect example.com:443 -servername example.com -showcerts
curl -vk --resolve example.com:443:<ip> https://example.com/
到期告警至少提前 30、14、7、3、1 天分级通知。
十三、真实客户端IP与安全边界
X-Forwarded-For 可被客户端伪造。只有来自可信代理地址的头才能被信任,应在入口覆盖或清洗,并记录真实连接地址和可信转发链。
PROXY protocol 需要两端同时启用,配置不一致会导致所有请求解析失败。变更时必须灰度。
十四、日志与指标
访问日志建议包含:
- request ID;
- 客户端和可信真实 IP;
- Host、方法、URI 模板;
- 状态、请求/响应字节;
- 总耗时、连接耗时、首字节时间;
- 上游地址和上游状态;
- 重试次数;
- TLS 协议和 SNI。
避免直接记录密码、Token、Cookie、身份证、手机号和完整请求体。
指标至少包括:请求率、错误率、延迟分位数、活跃连接、排队、无健康后端、重试、熔断、连接失败、TLS 握手和配置重载状态。
十五、502/504排障路线
- 确认错误由哪一层返回;
- 按 request ID 找代理和应用日志;
- 检查当时是否有健康后端;
- 区分连接失败、响应头失败、读取超时;
- 从代理主机直连同一后端;
- 检查 DNS、路由、防火墙、SNAT 和端口;
- 检查应用线程池、GC、数据库和下游依赖;
- 检查超时和重试是否放大;
- 对比变更和发布时点。
不要仅通过把 proxy_read_timeout 调大来“修复”504。这通常只会让请求占用资源更久。
十六、配置发布
安全流程:
- 配置进入 Git;
- 格式、语法和策略检查;
- 测试环境流量回放;
- 生成完整展开配置与差异;
- 同行评审;
- 单实例灰度;
- 验证错误率、延迟和连接;
- 分批推广;
- 保存版本并能一键回退。
动态配置也要版本化,不能因为“无需重启”就跳过评审。
十七、容量与压测
压测要包含真实 TLS、请求大小、长短连接、HTTP 版本、响应时间和后端行为。记录 CPU 单核、内存、网卡、连接、端口、代理队列和后端 P99。
容量不是单一 QPS。还要说明:
- 指定延迟 SLO 下的安全 QPS;
- 单节点故障后的剩余容量;
- 发布和证书轮换期间容量;
- 突发流量可维持时间;
- 限流与降级触发点。
十八、上线清单
- [ ] 完整链路、错误归属和超时预算已记录;
- [ ] 健康检查、慢启动和摘除阈值经过验证;
- [ ] 重试仅用于幂等请求且有预算;
- [ ] 连接池、并发、队列和限流有上限;
- [ ] 真实 IP 只信任受控代理;
- [ ] TLS 版本、证书链和到期告警正常;
- [ ] 日志可关联但不泄露敏感数据;
- [ ] 配置经过语法、差异和灰度检查;
- [ ] 502/504、节点失效和过载降级已演练;
- [ ] 单节点或单可用区故障后仍有容量余量。
十九、结语
流量入口的可靠性来自清晰的超时预算、有限的重试、受控的连接和可验证的健康检查。遇到故障时先确定错误在哪一层生成,再沿 request ID 和时间线定位;真正好的代理配置不是“永不报错”,而是在下游异常时快速、可控地失败,保护整个系统恢复。
参考资料
- Nginx Documentation:https://nginx.org/en/docs/
- HAProxy Documentation:https://docs.haproxy.org/
- Envoy Documentation:https://www.envoyproxy.io/docs