【问题标题】:axios post socket hang up only in dockeraxios post socket 仅在 docker 中挂断
【发布时间】:2020-08-14 21:16:57
【问题描述】:

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

直接在我的机器上运行代码时,axios 正确地等待响应,10 分钟后我收到 200 OK。在 docker(node: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',
  ...
}

【问题讨论】:

    标签: node.js docker http request axios


    【解决方案1】:

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

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

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

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

    “无法在根网络命名空间中启用网络运行:未知”

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

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

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

    "使用命令ip link可以显示本地配置的网卡及其MTU:"

    “如果出接口(本例为ens3)的MTU小于1500,则需要采取一些措施。如果大于等于1500,则此问题不适用于您。”

    我将 /etc/docker/daemon.json 文件编辑为如下所示:

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

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

    希望这可以帮助你或其他人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-09
      • 2022-11-10
      • 2017-10-20
      • 2019-07-27
      • 2019-07-23
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多