關於Node.js的httpClieint請求報錯ECONNRESET的緣由和解決措施

背景說明

最近在工做項目中有下面一個場景:node

使用Node.js的express框架實現了一個文件系統服務器端,其中有個API用於客戶端上傳文件。客戶端使用Node.js的HttpClient來調用服務器端的API上傳文件。git

客戶端在上傳小文件時沒有任何問題,在上傳大文件時httpClient請求報錯了下面的錯誤,github

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

google了不少資料,最後看了一下Node.js的相關源碼終於知道了該問題的緣由和解決辦法。express

問題緣由

出現該問題的緣由是:Node.js提供的HttpServer默認設置了超時時間爲2分鐘,當一個請求的處理時間超過2分鐘,HttpServer會自動將該請求的socket關閉掉,因而客戶端便收到了 ECONNRESET 的錯誤信息了。能夠參考Node.js的源碼bash

下面咱們使用了一個例子來驗證一下。服務器

服務器端:app

服務器端使用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......");
});

客戶端:socket

客戶端經過調用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)

相關文章
相關標籤/搜索