【问题标题】:Nginx upstream prematurely closed connection while reading response header from upstream, for large requestsNginx上游过早关闭连接,同时从上游读取响应标头,用于大型请求
【发布时间】:2016-07-29 01:45:17
【问题描述】:

我正在使用 nginx 和节点服务器来处理更新请求。当我请求更新大数据时,网关超时。我从 nginx 错误日志中看到了这个错误:

2016/04/07 00:46:04 [错误] 28599#0: *1 上游过早关闭 从上游读取响应标头时连接,客户端: 10.0.2.77,服务器:gis.oneconcern.com,请求:“GET /update_mbtiles/atlas19891018000415 HTTP/1.1”,上游: “http://127.0.0.1:7777/update_mbtiles/atlas19891018000415”,主持人: “gis.oneconcern.com”

我搜索了错误并尝试了所有可能的方法,但我仍然收到错误。

我的 nginx conf 有这些代理设置:

    ##
    # Proxy settings
    ##

    proxy_connect_timeout 1000;
    proxy_send_timeout 1000;
    proxy_read_timeout 1000;
    send_timeout 1000;

这就是我的服务器的配置方式

server {
listen 80;

server_name gis.oneconcern.com;
access_log /home/ubuntu/Tilelive-Server/logs/nginx_access.log;
error_log /home/ubuntu/Tilelive-Server/logs/nginx_error.log;

large_client_header_buffers 8 32k;
location / {
    proxy_pass http://127.0.0.1:7777;
    proxy_redirect off;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $http_host;
    proxy_cache_bypass $http_upgrade;
}

location /faults {
    proxy_pass http://127.0.0.1:8888;
    proxy_http_version 1.1;
    proxy_buffers 8 64k;
    proxy_buffer_size 128k;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

}

我正在使用 nodejs 后端来为 aws 服务器上的请求提供服务。仅当更新需要很长时间(大约 3-4 分钟)时才会出现网关错误。对于较小的更新,我没有收到任何错误。任何帮助将不胜感激。

节点js代码:

app.get("/update_mbtiles/:earthquake", function(req, res){
var earthquake = req.params.earthquake
var command = spawn(__dirname + '/update_mbtiles.sh', [ earthquake, pg_details ]);
//var output  = [];

command.stdout.on('data', function(chunk) {
//    logger.info(chunk.toString());
//     output.push(chunk.toString());
});

command.stderr.on('data', function(chunk) {
  //  logger.error(chunk.toString());
 //   output.push(chunk.toString());
});

command.on('close', function(code) {
    if (code === 0) {
        logger.info("updating mbtiles successful for " + earthquake);
        tilelive_reload_and_switch_source(earthquake);
        res.send("Completed updating!");
    }
    else {
        logger.error("Error occured while updating " + earthquake);
        res.status(500);
        res.send("Error occured while updating " + earthquake);
    }
});
});

function tilelive_reload_and_switch_source(earthquake_unique_id) {
tilelive.load('mbtiles:///'+__dirname+'/mbtiles/tipp_out_'+ earthquake_unique_id + '.mbtiles', function(err, source) {
    if (err) {
        logger.error(err.message);
        throw err;
    }
    sources.set(earthquake_unique_id, source); 
    logger.info('Updated source! New tiles!');
});
}

谢谢。

【问题讨论】:

  • 这个问题对我有帮助,我在接受http2 请求时错过了proxy_http_version 1.1;

标签: node.js nginx webserver


【解决方案1】:

我通过为代理设置更高的超时值解决了这个问题:

location / {
    proxy_read_timeout 300s;
    proxy_connect_timeout 75s;
    proxy_pass http://localhost:3000;
}

文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html

【讨论】:

  • 根据 NGINX 文档,连接超时不能超过 75 秒“定义与代理服务器建立连接的超时。需要注意的是,这个超时通常不能超过 75 秒。”
  • proxy_read_timeout 300s; proxy_connect_timeout 75s;从 Plesk Obsidian 中的日志/proxy_error_log 修复此错误消息“上游过早关闭连接,同时从上游读取响应标头”
【解决方案2】:

我认为来自 Nginx 的错误表明连接已被您的 nodejs 服务器关闭(即“上游”)。 nodejs是如何配置的?

【讨论】:

  • 哦!我发现我的节点服务器对大数据请求发送空响应。
  • 嗨@DivyaKonda,您能否详细说明一下服务空响应如何导致网关超时错误?
  • 可能是你的nodejs服务器超时(默认2分钟),超时服务器会发送空响应。文档:nodejs.org/api/http.html#http_server_settimeout_msecs_callback
  • 嗨@DivyaKonda你能解释一下你是如何修复它的吗?
【解决方案3】:

我有很长一段时间都遇到同样的错误,这里为我解决了这个问题。

我只是在服务中声明我使用以下内容:

Description= Your node service description
After=network.target

[Service]
Type=forking
PIDFile=/tmp/node_pid_name.pid
Restart=on-failure
KillSignal=SIGQUIT
WorkingDirectory=/path/to/node/app/root/directory
ExecStart=/path/to/node /path/to/server.js

[Install]
WantedBy=multi-user.target

这里应该引起您注意的是“After=network.target”。 我花了几天时间寻找 nginx 方面的修复程序,而问题就是这样。 可以肯定的是,停止运行您拥有的节点服务,直接启动 ExecStart 命令并尝试重现错误。如果它没有弹出,则仅表示您的服务有问题。至少我是这样找到答案的。

祝大家好运!

【讨论】:

  • 经过进一步调查,它看起来像是一个systemd 配置文件,而After=network.target 设置试图延迟该nodejs服务的启动,直到系统的网络启动并运行之后。
【解决方案4】:

我不认为这是你的情况,但如果它对任何人有帮助,我会发布它。我有同样的问题,问题是节点根本没有响应(我有一个条件,失败时没有做任何事情 - 所以没有响应) - 所以如果增加所有超时都不能解决它,请确保所有场景都会得到响应。

【讨论】:

    【解决方案5】:

    你可以像这样增加节点的超时时间。

    app.post('/slow/request', function(req, res) {
        req.connection.setTimeout(100000); //100 seconds
        ...
    }
    

    【讨论】:

      【解决方案6】:

      我也遇到了这个问题并找到了这篇文章。最终,这些答案都没有解决我的问题,相反,我不得不输入一个重写规则来删除location /rt,因为我的开发人员制作的后端并不期待任何额外的路径:

      ┌─(william@wkstn18)──(Thu, 05 Nov 20)─┐
      └─(~)──(16:13)─>wscat -c ws://WebsocketServerHostname/rt
      error: Unexpected server response: 502
      

      使用 wscat 反复测试给出 502 响应。 Nginx 错误日志提供了与上述相同的上游错误,但请注意上游字符串显示 GET 请求正在尝试访问 localhost:12775/rt 而不是 localhost:12775:

       2020/11/05 22:13:32 [error] 10175#10175: *7 upstream prematurely closed
       connection while reading response header from upstream, client: WANIP,
       server: WebsocketServerHostname, request: "GET /rt/socket.io/?transport=websocket
       HTTP/1.1", upstream: "http://127.0.0.1:12775/rt/socket.io/?transport=websocket",
       host: "WebsocketServerHostname"
      

      由于开发人员没有将他们的 websocket(监听 12775)编码为期望 /rt/socket.io 而只是 /socket.io/(注意:/socket.io/ 似乎只是指定 websocket 传输的一种方式讨论here)。因此,我没有要求他们重写他们的套接字代码,而是输入一个重写规则来将 WebsocketServerHostname/rt 转换为 WebsocketServerHostname:12775,如下所示:

      upstream websocket-rt {
              ip_hash;
      
              server 127.0.0.1:12775;
      }
      
      server {
              listen 80;
              server_name     WebsocketServerHostname;
      
              location /rt {
                      proxy_http_version 1.1;
      
                      #rewrite /rt/ out of all requests and proxy_pass to 12775
                      rewrite /rt/(.*) /$1  break;
      
                      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                      proxy_set_header Host $host;
      
                      proxy_pass http://websocket-rt;
                      proxy_set_header Upgrade $http_upgrade;
                      proxy_set_header Connection $connection_upgrade;
              }
      
      }
      

      【讨论】:

        【解决方案7】:

        在尝试从 Nginx 代理的服务器下载 2GB 文件时,我偶然发现了 *145660 upstream prematurely closed connection while reading upstream Nginx 错误日志条目。该消息表明“上游”关闭了连接,但实际上它与proxy_max_temp_file_size设置有关:

        语法:proxy_max_temp_file_size 大小;
        默认值:proxy_max_temp_file_size 1024m;
        上下文:http、服务器、位置

        当启用来自代理服务器的响应缓冲,并且整个响应不适合由 proxy_buffer_size 和 proxy_buffers 指令设置的缓冲区时,可以将部分响应保存到临时文件中。该指令设置临时文件的最大大小。一次写入临时文件的数据大小由 proxy_temp_file_write_size 指令设置。

        零值禁用对临时文件的响应缓冲。

        此限制不适用于将缓存或存储在磁盘上的响应。

        症状:

        • 下载被强制停止在 1GB 左右,
        • Nginx 声称上游关闭了连接,但没有代理服务器正在返回完整内容。

        解决办法:

        • 将代理位置的 proxy_max_temp_file_size 增加到 4096m 并开始发送完整内容。

        【讨论】:

          【解决方案8】:

          当我尝试向我的 api 发布大约 50 万行时,我在 AWS Elastic Beanstalk 实例的日志中发现了这个错误。

          我听从了这里的所有建议,但无济于事。

          最终奏效的是将我的 EC2 实例的大小从 1 核和 1GB RAM 增加到 4 核和 8 GB RAM。

          【讨论】:

            【解决方案9】:

            我遇到了同样的问题,这里详述的解决方案没有一个对我有用... 首先我有一个错误 413 Entity too large 所以我更新了我的 nginx.conf 如下:

            http {
                    # Increase request size
                    client_max_body_size 10m;
            
                    ##
                    # Basic Settings
                    ##
            
                    sendfile on;
                    tcp_nopush on;
                    tcp_nodelay on;
                    keepalive_timeout 65;
                    types_hash_max_size 2048;
                    # server_tokens off;
            
                    # server_names_hash_bucket_size 64;
                    # server_name_in_redirect off;
            
                    include /etc/nginx/mime.types;
                    default_type application/octet-stream;
            
                    ##
                    # SSL Settings
                    ##
            
                    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
                    ssl_prefer_server_ciphers on;
            
                    ##
                    # Logging Settings
                    ##
            
                    access_log /var/log/nginx/access.log;
                    error_log /var/log/nginx/error.log;
            
                    ##
                    # Gzip Settings
                    ##
            
                    gzip on;
            
                    # gzip_vary on;
                    # gzip_proxied any;
                    # gzip_comp_level 6;
                    # gzip_buffers 16 8k;
                    # gzip_http_version 1.1;
                    # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
            
                    ##
                    # Virtual Host Configs
                    ##
            
                    include /etc/nginx/conf.d/*.conf;
                    include /etc/nginx/sites-enabled/*;
            
                    ##
                    # Proxy settings
                    ##
                    proxy_connect_timeout 1000;
                    proxy_send_timeout 1000;
                    proxy_read_timeout 1000;
                    send_timeout 1000;
            }
            

            所以我只更新了 http 部分,现在我遇到了错误 502 Bad Gateway,当我显示 /var/log/nginx/error.log 时,我得到了著名的“上游过早关闭连接,同时从上游读取响应头”

            对我来说真正神秘的是,当我在服务器上使用 virtualenv 运行请求并将请求发送到:IP:8000/nameOfTheRequest

            感谢阅读

            【讨论】:

              【解决方案10】:

              我遇到了同样的错误,这是我的解决方法:

              • 从 AWS 下载的日志。
              • 已查看 Nginx 日志,没有上述其他详细信息。
              • 查看了 node.js 日志,AccessDenied AWS SDK 权限错误。
              • 检查了 AWS 试图从中读取的 S3 存储桶。
              • 添加了具有读取权限的附加存储桶以更正服务器角色。

              即使我正在处理大型文件,在更正丢失的 S3 访问权限后,我也无需更改其他错误或设置。

              【讨论】:

                【解决方案11】:

                问题

                上游服务器超时,我不知道发生了什么。

                如果您的服务器正在连接到数据库,则在增加读取或写入超时之前首先查看的位置

                服务器正在连接到数据库,并且该连接工作正常并且在正常的响应时间内,它不是导致服务器响应时间延迟的原因。

                确保连接状态不会导致上游发生级联故障

                那你就可以动起来看看服务器和代理的读写超时配置了。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2018-03-12
                  • 2018-09-21
                  • 2018-06-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-04-02
                  • 2015-08-08
                  • 1970-01-01
                  相关资源
                  最近更新 更多