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排障路线

  1. 确认错误由哪一层返回;
  2. 按 request ID 找代理和应用日志;
  3. 检查当时是否有健康后端;
  4. 区分连接失败、响应头失败、读取超时;
  5. 从代理主机直连同一后端;
  6. 检查 DNS、路由、防火墙、SNAT 和端口;
  7. 检查应用线程池、GC、数据库和下游依赖;
  8. 检查超时和重试是否放大;
  9. 对比变更和发布时点。

不要仅通过把 proxy_read_timeout 调大来“修复”504。这通常只会让请求占用资源更久。

十六、配置发布

安全流程:

  1. 配置进入 Git;
  2. 格式、语法和策略检查;
  3. 测试环境流量回放;
  4. 生成完整展开配置与差异;
  5. 同行评审;
  6. 单实例灰度;
  7. 验证错误率、延迟和连接;
  8. 分批推广;
  9. 保存版本并能一键回退。

动态配置也要版本化,不能因为“无需重启”就跳过评审。

十七、容量与压测

压测要包含真实 TLS、请求大小、长短连接、HTTP 版本、响应时间和后端行为。记录 CPU 单核、内存、网卡、连接、端口、代理队列和后端 P99。

容量不是单一 QPS。还要说明:

  • 指定延迟 SLO 下的安全 QPS;
  • 单节点故障后的剩余容量;
  • 发布和证书轮换期间容量;
  • 突发流量可维持时间;
  • 限流与降级触发点。

十八、上线清单

  • [ ] 完整链路、错误归属和超时预算已记录;
  • [ ] 健康检查、慢启动和摘除阈值经过验证;
  • [ ] 重试仅用于幂等请求且有预算;
  • [ ] 连接池、并发、队列和限流有上限;
  • [ ] 真实 IP 只信任受控代理;
  • [ ] TLS 版本、证书链和到期告警正常;
  • [ ] 日志可关联但不泄露敏感数据;
  • [ ] 配置经过语法、差异和灰度检查;
  • [ ] 502/504、节点失效和过载降级已演练;
  • [ ] 单节点或单可用区故障后仍有容量余量。

十九、结语

流量入口的可靠性来自清晰的超时预算、有限的重试、受控的连接和可验证的健康检查。遇到故障时先确定错误在哪一层生成,再沿 request ID 和时间线定位;真正好的代理配置不是“永不报错”,而是在下游异常时快速、可控地失败,保护整个系统恢复。

参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-28 21:12:05

results matching ""

    No results matching ""