axios柱插座仅在docker中挂起



我有一台服务器,它需要10分钟以上的时间才能开始响应请求。我有一个nodejs客户端,它使用axios向该服务器发送post请求。我已将axios超时设置为30分钟。

当直接在我的机器上运行代码时,axios会正确地等待响应,10分钟后我会收到200 OK。当在docker中运行相同的脚本(节点:10基本映像(时,5.5分钟后我收到一个套接字挂起错误。

服务器:

const http = require('http')
const server = http.createServer(function (request, response) {
if (request.method == 'POST') {
var body = ''
request.on('data', function (data) { 
body += data
console.log('Partial body: ' + body)
})
request.on('end', function () {
setTimeout(() => {
response.writeHead(200, { 'Content-Type': 'text/html' })
response.end('post received')
}, 1000 * 60 * 10);
});
} else {
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('Ok');
}
})
const port = 5000
const host = '10.0.0.50'
server.setTimeout(1000 * 60 * 30);
server.listen(port, host)
console.log(`Listening at http://${host}:${port}`)

客户端:

let axios = require('axios');
async function run () {
const axiosInstance = axios.create({
baseURL: 'http://livedoc.transmissionmedia.ca/',
timeout: (1000 * 60 * 30),
});
axiosInstance.defaults.timeout = (1000 * 60 * 30);
console.log(`${new Date().toISOString()} - start`);
// const resp = await axiosInstance.post(`http://10.0.0.50:5000/weatherforecast`);
const resp = await axiosInstance({
method: 'post',
url: `http://10.0.0.50:5000/weatherforecast`,
timeout: 1000 * 60 * 30
});
// const resp = await axiosInstance.post(`http://10.0.0.50:5000/weatherforecast`);
console.log(`${new Date().toISOString()} - end`);
}
run()
.then(() => {  console.error('Succeeded!');  process.exit(0); })
.catch(err => { console.error('Failed!'); console.error(err); process.exit(-1); });

当客户端脚本在docker容器中运行时,大约5.5分钟后我收到以下错误:

{ Error: socket hang up
at createHangUpError (_http_client.js:332:15)
at Socket.socketOnEnd (_http_client.js:435:23)
at Socket.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
code: 'ECONNRESET',
...
}

我不知道这是否是解决问题的方法,但我遇到了一个套接字挂起问题,API调用仅在docker中运行,在Google计算引擎上运行。

当我直接执行代码时,这很好,当我在docker中运行相同的代码时,如果有效负载大于一些看似任意但不固定的大小,我会收到套接字挂起错误(ERRCONNRESET(。

最后,问题是默认docker网桥网络的MTU与主机网络的MTU不匹配。

我也尝试过--network=host,但我得到了错误:

"无法在根网络命名空间中启用网络的情况下运行:未知";

这显然是其他人从未见过的。

最后,我遵循了这里关于如何配置docker网桥网络MTU的建议:

https://mlohr.com/docker-mtu/

"使用命令ip链接,您可以显示本地配置的网卡及其MTU:";

"如果传出接口(在本例中为ens3(的MTU小于1500,则需要执行一些操作。如果大于或等于1500,则此问题不适用于您">

我编辑了我的/etc/docker/daemon.json文件,如下所示:

{
"runtimes": {
"runsc": {
"path": "/usr/bin/runsc"
}
},
"mtu": 1460
}

其中1460是主机网络接口的MTU,问题解决了!

希望这能帮助到你或其他人,这让我头疼。

最新更新