I have some timeout problems when calling multiple times an HTTP[S] endpoint from node.js inside an Azure App Service.
Here my code to demostrate the problem.
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);
});
When running this app 3 or 4 times inside a Standard Medium App Service (I'm running it using Kudu but I discover this error inside a standard web app) I get the following error for every requests:
{ 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' }
After some minutes (5/6) without performing requests the above code works again.
I have tried with both node-fetch
(https://www.npmjs.com/package/node-fetch) and request
(https://www.npmjs.com/package/request). Same results.
The same problem occurs if I not specify an agent
and is not related to the destination endpoint, I have tried with many different endpoints (private or public).
According to Microsoft Best Practices node.js applications should use a keep alive agent
with the following configuration:
var keepaliveAgent = new Agent({
maxSockets: 40,
maxFreeSockets: 10,
timeout: 60000,
keepAliveTimeout: 300000
});
In fact when creating the agent with:
const agent = new https.Agent({ maxSockets: 100 });
everything works as expected.
Is this behavior expected? What is the best practice for node.js? It is fine to always specify an agent
with maxSockets
also outside Azure?
UPDATE:
The other strange behavior is that if I run the above code using node index
3 or 4 times I expect that connections are closed when node process exit, but seems that the connections remain open for some minutes. This can be the effect of the TIME_WAIT state?