关于Node.js的httpClieint请求报错ECONNRESET的原因和解决措施

Posted lienhua34

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于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)

以上是关于关于Node.js的httpClieint请求报错ECONNRESET的原因和解决措施的主要内容,如果未能解决你的问题,请参考以下文章

node.js关于node.js,如何解决npm should be run outside of the Node.js REPL, in your normal shell报错?

node.js关于node.js,如何解决npm should be run outside of the Node.js REPL, in your normal shell报错?

node.js关于node.js,如何解决npm should be run outside of the Node.js REPL, in your normal shell报错?

关于Node.js中HTTP请求返回数据需要JSON解析的问题

Node.js关于微信支付V3版相关处理方法

关于node.js内部异步I/O机制的困惑