高负载下OpenResty报99:Address not available且返回502如何排查解决
OpenResty代理高负载下Address not available报错排查方案
[crit] 10#10: *451875 connect() to 100.xx.xx.xxx:80 failed (99: Address not available) 错误本质是代理作为客户端向上游发起连接时,系统没有可用的本地端口分配给新连接,导致连接创建失败,最终触发502响应。你已经调整了ulimit和临时端口范围仍未解决,可按照以下步骤逐层排查:
1. 排查K8s Pod层面的参数透传问题
跑在K8s中的服务默认不会继承节点的内核参数和ulimit配置,你调整的节点参数很可能没有生效:
- 确认Pod内实际生效的ulimit:执行
kubectl exec -it <openresty-pod名称> -- ulimit -n,检查open files软硬限制是否符合预期,如未生效需要在Deployment的securityContext中显式配置:
spec: template: spec: securityContext: sysctls: - name: fs.file-max value: "2097152" - name: net.core.somaxconn value: "65535" containers: - name: openresty # 你的其他配置 securityContext: capabilities: add: ["NET_ADMIN"] resources: limits: nofile: soft: 65535 hard: 65535
注意:上述sysctls属于非安全内核参数,需要先调整kubelet启动参数,添加--allowed-unsafe-sysctls='net.*,fs.*'配置,否则Pod会无法调度。
- 确认Pod内实际生效的临时端口范围:执行
kubectl exec -it <openresty-pod名称> -- cat /proc/sys/net/ipv4/ip_local_port_range,默认范围是32768 60999,建议调整为1024 65535,未生效的话同样通过上述sysctls配置添加net.ipv4.ip_local_port_range = 1024 65535。 - 排查conntrack表溢出:执行
sysctl net.netfilter.nf_conntrack_count和sysctl net.netfilter.nf_conntrack_max,如果count数值接近max,需要调大net.netfilter.nf_conntrack_max参数到1048576或更高。
2. 调整TCP TIME_WAIT回收策略
高负载短连接场景下,TIME_WAIT状态的连接会占用大量本地端口,仅调整端口范围不足以解决问题:
- 先确认TIME_WAIT数量:在Pod内执行
ss -s,如果TIME_WAIT连接数超过临时端口范围的2/3,即为核心问题。 - 在Pod的sysctls配置中添加以下参数:
net.ipv4.tcp_tw_reuse = 1:允许复用TIME_WAIT状态的socket用于新的TCP连接,对客户端侧的代理场景完全安全net.ipv4.tcp_fin_timeout = 15:将TIME_WAIT超时时间从默认60s缩短为15s,加快端口回收速度net.ipv4.tcp_max_tw_buckets = 262144:调大系统允许的最大TIME_WAIT连接数,避免超出阈值后内核直接丢弃新连接- 注意:
net.ipv4.tcp_tw_recycle参数必须设为0,K8s为NAT网络环境,开启该参数会导致大量连接异常。
3. 优化OpenResty上游连接配置
默认OpenResty向上游发起的是短连接,高负载下会频繁创建销毁连接,极容易耗尽端口,建议开启上游长连接:
- 修改upstream配置,添加长连接相关参数:
upstream 你的上游服务标识 { server 100.xx.xx.xxx:80; keepalive 1024; # 空闲长连接的最大保留数量,可根据QPS调整为2048/4096 keepalive_requests 10000; # 单个长连接最多处理的请求数 keepalive_timeout 60s; # 空闲长连接的超时时间 }
- 在对应proxy的location配置块中添加上行长连接参数:
location / { proxy_pass http://你的上游服务标识; proxy_http_version 1.1; proxy_set_header Connection ""; # 清除客户端传入的Connection头,强制使用长连接访问上游 # 其他proxy配置 }
4. 高负载时现场排查
如果调整完上述配置仍有问题,可在故障发生时采集以下数据定位根因:
- 执行
ss -tanp | grep :80 | awk '{print $1}' | sort | uniq -c统计各TCP连接状态的数量 - 执行
dmesg | grep -i tcp检查内核日志是否有TCP相关的报错 - 执行
cat /proc/net/sockstat查看socket整体使用情况
内容的提问来源于stack exchange,提问作者K.Thanvi
相关产品推荐
相关产品推荐

