本文编写于 238 天前,最后修改于 238 天前,其中某些信息可能已经过时。

背景与现象

使用场景为nginx反代harbor,配置文件如下

server {
  listen 80;
  listen 443 ssl;
  listen [::]:80;
  listen [::]:443 ssl;
  server_name reg.senayuki.moe;

  ssl_certificate      /etc/nginx/ssl/reg.senayuki.moe.fullchain.cer;
  ssl_certificate_key  /etc/nginx/ssl/reg.senayuki.moe.key;

  client_max_body_size 0;
  chunked_transfer_encoding on;

  location / {
      proxy_pass http://192.168.1.101/;
      proxy_set_header  Host              $http_host;
      proxy_set_header  X-Real-IP         $remote_addr;
      proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header  X-Forwarded-Proto $scheme;

      proxy_buffering off;
      proxy_request_buffering off;
  }
}

看似配置没有什么问题,启用了chunked_transfer_encoding、关闭了proxy_bufferingproxy_request_buffering,我认为现在nginx应当直接中继请求给harbor,不再有buffer了,但却出现了问题:
当我上传一个超大的镜像时一直在失败重试,上传时流入与流出的网络流量竟然极度不对等(流入500Mbps,流出只有3Mbps),磁盘被疯狂写入,如果磁盘被写满,那就500了,这才注意到buffer仍然在作用

解决

阅读nginx文档,发现proxy_request_buffering参数有这样一句说明

When HTTP/1.1 chunked transfer encoding is used to send the original request body, the request body will be buffered regardless of the directive value unless HTTP/1.1 is enabled for proxying.

这时我的第一反应,就是把chunked_transfer_encoding给off掉了………………结果并没有什么作用
最后根据文档指引,增加了一行proxy_http_version 1.1,启用HTTP 1.1代理,终于正常了

解决办法很简单,但是好坑,简单记录一下