背景說明
最近在工作項目中有下面一個場景:
使用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)
