nginx 反向代理
📌 现象描述:间歇性“网络连接错误”
典型表现: 前端或客户端在高并发或长时间运行后,随机弹出“网络连接错误”或 502/504 报错。
特征:
非永久性: 用户刷新或重试后通常能立即恢复。
负载相关: 业务高峰期出现频率显著增高。
假象: 后端服务进程依然在线,CPU/内存未爆满,但连接链路出现瞬时断裂。
🛠 解决办法
问题根源: 默认配置下,Nginx 对后端(Golang)使用短连接。每笔请求都经历“三次握手 -> 数据传输 -> 四次挥手”,在高并发下会导致 Nginx 服务器产生大量 TIME_WAIT 状态的连接,从而耗尽临时端口或导致连接建立延迟。
优化方案: 启用 upstream 与 Keepalive 机制。
code
Nginx
upstream backend_pool {
server 127.0.0.1:8080;
# 保持在长连接池中的空闲连接数,建议根据并发量设为 32-128
keepalive 64;
}
server {
location /api/ {
proxy_pass http://backend_pool;
# 必须配置:强制使用 HTTP/1.1 协议以支持长连接
proxy_http_version 1.1;
# 必须配置:清除 Connection 头部,防止被设为 "close"
proxy_set_header Connection "";
# 适当延长超时时间,防止网络抖动导致的断开
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
}
}
问题根源: 如果 MaxOpenConns 过小,高并发请求会在连接池外排队。当排队时长超过 Nginx 的等待时间或客户端超时时间,就会报“网络错误”。
优化方案: 科学配置 sql.DB 参数。
code
Go
// 建议在初始化数据库时显式配置
db.SetMaxOpenConns(100) // 最大打开连接数(根据数据库规格定,避免撑爆数据库)
db.SetMaxIdleConns(20) // 最大空闲连接数(减少频繁创建连接的开销)
db.SetConnMaxLifetime(5 * time.Minute) // 连接生命周期(需小于数据库本身的 wait_timeout)
db.SetConnMaxIdleTime(2 * time.Minute) // 空闲连接回收时间
注意:连接数不是越大越好,应通过压测观察数据库 CPU 负载来决定上限。
🔍 综合排查与预防
日志联动分析:
检查 Nginx error_log:确认是 upstream timed out (后端慢) 还是 cannot assign requested address (本地端口耗尽)。
检查 Golang 日志:观察是否有数据库连接超时或 Context Deadline Exceeded。
压测复现: 使用 wrk 或 JMeter 模拟并发。例如:wrk -t12 -c400 -d30s http://api_url,观察错误是否在并发压力提升时复现。
系统内核调优: 若并发极高(万级以上),需检查 Linux 内核参数 net.ipv4.tcp_tw_reuse = 1 以允许重用 TIME_WAIT 状态的套接字。
结论: 该问题通常不是“断网”,而是“连接管理策略失效”。通过 Nginx 长连接复用和 Golang 连接池的平滑扩容,可以解决 90% 以上的此类间歇性报错。
浙公网安备 33010602011771号