關於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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM