zoukankan      html  css  js  c++  java
  • 关于Node.js的httpClieint请求报错ECONNRESET的原因和解决措施

    背景说明

    最近在工作项目中有下面一个场景:

    使用Node.js的express框架实现了一个文件系统服务器端,其中有个API用于客户端上传文件。客户端使用Node.js的HttpClient来调用服务器端的API上传文件。

    客户端在上传小文件时没有任何问题,在上传大文件时httpClient请求报错了下面的错误,

    { [Error: socket hang up] code: 'ECONNRESET' } 
    

    google了很多资料,最后看了一下Node.js的相关源码终于知道了该问题的原因和解决办法。

    问题原因

    出现该问题的原因是:Node.js提供的HttpServer默认设置了超时时间为2分钟,当一个请求的处理时间超过2分钟,HttpServer会自动将该请求的socket关闭掉,于是客户端便收到了 ECONNRESET 的错误信息了。可以参考Node.js的源码

    下面我们使用了一个例子来验证一下。

    服务器端:

    服务器端使用express框架,注册了一个路径为““ 的 GET 方法路由处理函数。在该路由处理函数中,通过setTimeout方式设置了超时处理,3分钟后超时才会对请求进行相应。

    const express = require('express');
    const util = require('util');
    const app = express();
    
    app.get("/", function(req, res, next) {
        util.log("Received a request.");
    
        setTimeout(function() {
            res.setHeader('transfer-encoding', 'chunked');
            res.status(200);
            util.log("timeout")
            res.write("hello world");
            res.end();
        }, 3 * 60 * 1000)
    });
    var server = app.listen(3001, function() {
        sutil.log("server listening at port 3001......");
    });

    客户端:

    客户端通过调用http.request方法请求服务器端的接口,并打印返回的信息。

    const http = require('http');
    const util = require('util')
    
    var opt = {
        host: 'localhost',
        port: 3001,
        method: 'GET',
    };
    var req = http.request(opt, function(res) {
        util.log('STATUS:', res.statusCode);
        res.setEncoding('utf8');
        var resultText = '';
        res.on('data', (chunk) => {
            resultText += chunk;
        });
        res.on('end', () => {
            util.log(resultText);
        });
    });
    
    req.on('error', (e) => {
        util.log(e);
    });
    
    util.log("start request...")
    req.end();

    先启动服务器端,然后启动客户端。请求的结果如下所示:

    服务器端:

    bbash-3.2$ node app.js                                                                                                                                                           
    12 Nov 21:02:16 - server listening at port 3001......                                                                                                                              
    12 Nov 21:02:22 - Received a request.                                                                                                                                               
    12 Nov 21:05:22 - timeout

    客户端:

    bash-3.2$ node app.js                                                                                                                                                               
    12 Nov 21:02:22 - start request...                                                                                                                                                  
    12 Nov 21:04:22 - { [Error: socket hang up] code: 'ECONNRESET' }

    通过上面的运行结果可以看到,客户端在请求等待了2分钟之后,就报错了 ECONNRESET 的错误。

    解决措施

    解决措施:调用服务器端的server.setTimeout()方法将服务器端的超时设置得大一点或者直接将超时机制关闭(将超时时间设置为0即可关闭)

    就使用上面的代码,客户端不变,服务器在文件最后调用server.setTimeout()方法,如下所示,

    var server = app.listen(3001, function() {
        sutil.log("server listening at port 3001......");
    });
    server.setTimeout(0)

    先启动服务器端,然后再启动客户端,运行结果如下:

    服务器端:

    bash-3.2$ node app.js    
    12 Nov 21:37:22 - server listening at port 3001......                                    
    12 Nov 21:37:29 - Received a request.                                                    
    12 Nov 21:40:29 - timeout

    客户端:

    bash-3.2$ node app.js         
    12 Nov 21:37:29 - start request...                                                       
    12 Nov 21:40:29 - STATUS: 200                                                            
    12 Nov 21:40:29 - hello world 

    从上面运行结果可见,客户端能够正常接收到服务器端的返回结果了。

    (done)

  • 相关阅读:
    django 设置局域网内访问项目
    104. Maximum Depth of Binary Tree
    multi dimension array
    Longest Plindrome Subarray
    BlockQueue
    H2O
    HoppingIterator
    midStack
    Reverse Words in a String II
    public boolean canPlaceFlowers(List<Boolean> flowerbed, int numberToPlace)
  • 原文地址:https://www.cnblogs.com/lienhua34/p/6057662.html
Copyright © 2011-2022 走看看