在不指定maxSockets的情况下调用HTTP终结点时在Azure App Service上连接ETIMEDOUT

Dav*_*rdi 5 azure node.js azure-web-sites azure-web-app-service node-fetch

从Azure App Service中的node.js多次调用HTTP [S]终结点时,我遇到一些超时问题。

这里是我的代码来说明问题。

const fetch = require('node-fetch');
const https = require("https");
const agent = new https.Agent();

function doWork() {
  const works = [];
  for (let i = 0; i < 50; i++) {
    const wk = fetch('https://www.microsoft.com/robots.txt', { agent })
    .then(res => res.text())
    .then(body => console.log("OK", i))
    .catch((err) => console.log("ERROR", i, err));
    works.push(wk);
  }

  return Promise.all(works);
}

doWork()
.catch((err) => {
  console.log(err);
});
Run Code Online (Sandbox Code Playgroud)

在标准中型应用程序服务中运行此应用程序3或4次(我正在使用Kudu运行它,但我在标准网络应用程序中发现此错误)时,对于每个请求都会收到以下错误:

{ FetchError: request to https://www.microsoft.com/robots.txt failed, reason: connect ETIMEDOUT 23.206.106.109:443
    at ClientRequest.<anonymous> (D:\home\site\test\test-forge-calls\node_modules\node-fetch\lib\index.js:1393:11)
    at emitOne (events.js:96:13)
    at ClientRequest.emit (events.js:188:7)
    at TLSSocket.socketErrorListener (_http_client.js:310:9)
    at emitOne (events.js:96:13)
    at TLSSocket.emit (events.js:188:7)
    at emitErrorNT (net.js:1276:8)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
  message: 'request to https://www.microsoft.com/robots.txt failed, reason: connect ETIMEDOUT 23.206.106.109:443',
  type: 'system',
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT' }
Run Code Online (Sandbox Code Playgroud)

几分钟(5/6)后,没有执行请求,以上代码再次起作用。

我已经尝试了node-fetchhttps://www.npmjs.com/package/node-fetch)和requesthttps://www.npmjs.com/package/request)。结果相同。如果我未指定an agent且与目标端点不相关,则会发生相同的问题,我尝试使用许多不同的端点(私有或公共)。

根据Microsoft最佳实践, node.js应用程序应使用agent以下配置保持活动:

var keepaliveAgent = new Agent({    
    maxSockets: 40,    
    maxFreeSockets: 10,    
    timeout: 60000,    
    keepAliveTimeout: 300000    
});
Run Code Online (Sandbox Code Playgroud)

实际上,使用以下方法创建代理时:

const agent = new https.Agent({ maxSockets: 100 });
Run Code Online (Sandbox Code Playgroud)

一切都按预期进行。

这是预期的行为吗?node.js的最佳实践是什么?这是罚款,始终指定agentmaxSockets也Azure的外面?

更新:

另一个奇怪的行为是,如果我使用node index3到4次运行上面的代码,我希望在节点进程退出时关闭连接,但是似乎连接会保持打开状态几分钟。这可能是TIME_WAIT状态的结果吗?