In the following nodejs program, I am patching the dns.lookup
function in order to investigate how a slow DNS lookup would behave when a timeout is set on a request. The DNS lookup will (appear to) take 10 seconds, so I expect my 1000ms timeout on the request to be triggered.
My timeout on the request is indeed triggered, but after around 5000ms instead of 1000ms as expected. Why could this be?
const dns = require('dns');
const http = require('http');
const lookup = dns.lookup;
const now = Date.now();
// I'm trying to simulate a slow DNS lookup here, to test how it behaves with the various nodejs
// timeout options.
dns.lookup = function patchedLookup(...args) {
setTimeout(() => {
lookup.apply(this, args);
}, 10_000);
};
const req = http.request('');
// The slow DNS lookup should cause this to timeout after 1000ms.
req.setTimeout(1000, () => {
// Logs something like "timed out after 5007ms" - why not after 1000ms?
console.error(`timed out after ${Date.now() - now}ms`);
req.abort();
});
req.on('error', (err) => {
console.error(`error after ${Date.now() - now}ms: ${err}`);
});
req.end();
In the following nodejs program, I am patching the dns.lookup
function in order to investigate how a slow DNS lookup would behave when a timeout is set on a request. The DNS lookup will (appear to) take 10 seconds, so I expect my 1000ms timeout on the request to be triggered.
My timeout on the request is indeed triggered, but after around 5000ms instead of 1000ms as expected. Why could this be?
const dns = require('dns');
const http = require('http');
const lookup = dns.lookup;
const now = Date.now();
// I'm trying to simulate a slow DNS lookup here, to test how it behaves with the various nodejs
// timeout options.
dns.lookup = function patchedLookup(...args) {
setTimeout(() => {
lookup.apply(this, args);
}, 10_000);
};
const req = http.request('http://joebarnett.xyz');
// The slow DNS lookup should cause this to timeout after 1000ms.
req.setTimeout(1000, () => {
// Logs something like "timed out after 5007ms" - why not after 1000ms?
console.error(`timed out after ${Date.now() - now}ms`);
req.abort();
});
req.on('error', (err) => {
console.error(`error after ${Date.now() - now}ms: ${err}`);
});
req.end();
Share
Improve this question
asked Mar 25 at 20:15
dipeadipea
5831 gold badge5 silver badges23 bronze badges
1 Answer
Reset to default 1The req.setTimeout()
timeout only starts being enforced after a socket is assigned to the request. If the request is still in the DNS resolution phase, the timeout will not be triggered until after the DNS lookup completes and a socket is assigned.
To enforce a total timeout, including DNS resolution, you can use a separate timer to wrap the entire request operation, including DNS resolution.
const dns = require('dns');
const http = require('http');
const lookup = dns.lookup;
const now = Date.now();
dns.lookup = function patchedLookup(...args) {
setTimeout(() => {
lookup.apply(this, args);
}, 10_000);
};
const globalTimeout = 1000;
const timer = setTimeout(() => {
console.error(`Global timeout after ${Date.now() - now}ms`);
req.abort();
}, globalTimeout);
const req = http.request('http://joebarnett.xyz', () => {
clearTimeout(timer);
});
req.setTimeout(globalTimeout, () => {
console.error(`Request timed out after ${Date.now() - now}ms`);
req.abort();
});
req.on('error', (err) => {
clearTimeout(timer);
console.error(`Error after ${Date.now() - now}ms: ${err}`);
});
This ensures the timeout applies to the entire lifecycle of the request, including DNS resolution.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744170852a4561527.html
评论列表(0条)