当在 Nginx 中设置 proxy_request_buffering off;
时,浏览器可能收到 RST(Reset)包,这通常与代理行为、HTTP协议交互或客户端/服务端超时机制有关。以下是原因分析和解决方案:
1. 核心原因
(1) 上游服务器(Upstream)处理不及时
- 现象:Nginx 关闭请求缓冲后,会立即将客户端的请求数据流式转发给上游服务器。如果上游服务器未及时读取数据(如阻塞或处理慢),而客户端已发送完请求(如 HTTP POST 大文件),Nginx 会强制关闭连接,触发 RST。
- 抓包特征:
- 客户端发送完最后一个 TCP 包后,收到服务端的 RST。
(2) HTTP Keepalive 冲突
- 场景:若客户端启用 Keepalive,但上游服务器不支持或主动关闭连接,Nginx 可能因协议不一致返回 RST。
- 验证方法:
curl -v -H "Connection: keep-alive" http://example.com
(3) SSL/TLS 代理问题
- HTTPS场景:若 Nginx 作为 SSL Termination Proxy,且上游服务证书校验失败或协议不匹配(如 HTTP/1.0 vs HTTP/1.1),可能直接断开连接。
2. Nginx相关配置检查
location / {
proxy_pass http://upstream_server;
proxy_request_buffering off;
# 关键优化参数
proxy_http_version 1.1; # 强制HTTP/1.1避免协议降级
proxy_set_header Connection ""; # 禁用Keepalive冲突
proxy_read_timeout 60s; # 延长上游读取超时
}
必须配合的参数
参数 | 作用 | 推荐值 |
---|---|---|
proxy_read_timeout |
等待上游响应的超时时间 | 根据业务调整(如60s) |
proxy_connect_timeout |
连接上游的超时时间 | 5s~15s |
proxy_send_timeout |
发送请求到上游的超时时间 | 60s |
3. Linux系统层排查
(1) Socket缓冲区溢出
- 检查命令:
netstat -s | grep -i "prune" # 查看TCP缓存丢弃统计 ss -tempo | grep -B10 "reset" # 检查Socket状态和计时器
- 解决方法:
sysctl -w net.ipv4.tcp_rmem="4096 87380 <最大缓冲区>"
(2) Conntrack表限制
- NAT环境下 conntrack表满可能导致RST:
sysctl net.netfilter.nf_conntrack_max=524288 #调大表项数量
4. Wireshark抓包分析示例
过滤条件建议:
tcp.flags.reset == 1 && ip.dst == <客户端IP> && tcp.port == <Nginx端口>
重点关注:
- RST包之前的最后一个HTTP请求是否完整。
- TIME_WAIT状态的连接是否被提前重置。
最终解决方案
根据场景选择以下修复方式:
临时规避
恢复proxy_request_buffering on;
(牺牲实时性换取稳定性)。彻底解决
- ✅ 确保上游服务能流式处理请求(如换用支持 chunked transfer的上游框架)。
- ✅ 调整 Nginx timeout参数匹配业务需求。
- ✅ 在负载均衡层禁用主动健康检查的RST行为(如AWS ALB需关闭TCP健康检查)。
- ✅ 确保上游服务能流式处理请求(如换用支持 chunked transfer的上游框架)。
如需进一步分析,请提供以下信息:
nginx.conf
中完整的server{}
配置片段。
curl -v
+tcpdump
的报错日志。
内容由零声教学AI助手提供,问题来源于学员提问