Итак, мы говорим здесь о типах тайм-аутов, один из которых связан с подключением к серверу (тайм-аут подключения), другой тайм-аут произойдет, когда данные не отправляются или не принимаются через сокет в течение некоторого времени (тайм-аут простоя).
Сокеты узла имеют тайм-аут сокета, который можно использовать для синтеза тайм-аута соединения и простоя. Это можно сделать, установив тайм-аут сокета на тайм-аут подключения, а затем, при подключении, установив его на тайм-аут простоя.
пример:
const request = http.request(url, {
timeout: connectTimeout,
});
request.setTimeout(idleTimeout);
Это работает, потому что таймаут в опциях выставляется сразу при создании сокета, функция setTimeout
запускается на сокете при подключении!
Во всяком случае, вопрос был о том, как проверить время ожидания подключения. Итак, давайте сначала припаркуем тайм-аут простоя. Мы можем просто проверить это, не отправляя никаких данных в течение некоторого времени, что приведет к тайм-ауту. Проверять!
Тайм-аут подключения проверить немного сложнее, первое, что приходит в голову, это то, что нам нужно место для подключения, к которому не будет ошибок, но и не будет подключаться. Это вызовет тайм-аут. Но как, черт возьми, мы можем смоделировать это в узле?
Если мы подумаем немного нестандартно, то сможем понять, что этот тайм-аут примерно равен времени, которое требуется для подключения. Неважно, почему соединение длится так долго. Нам просто нужно отсрочить время, необходимое для подключения. Это не обязательно серверная вещь, мы также можем сделать это на клиенте. В конце концов, это часть подключения, если мы можем задержать ее там, мы можем проверить тайм-аут.
Так как же мы можем задержать соединение на стороне клиента? Что ж, для этого мы можем использовать поиск DNS. Перед подключением выполняется поиск DNS. Если мы просто задержим это на 5 секунд или около того, мы сможем очень легко проверить время ожидания соединения.
Вот как может выглядеть код:
import * as dns from "dns";
import * as http from "http";
const url = new URL("http://localhost:8080");
const request = http.request(url, {
timeout: 3 * 1000, // connect timeout
lookup(hostname, options, callback) {
setTimeout(
() => dns.lookup(hostname, options, callback),
5 * 1000,
);
},
});
request.setTimeout(10 * 1000); // idle timeout
request.addListener("timeout", () => {
const message = !request.socket || request.socket.connecting ?
`connect timeout while connecting to ${url.href}` :
`idle timeout while connected to ${url.href}`;
request.destroy(new Error(message));
});
В своих проектах я обычно использую инъекционный агент. Затем агент выполняет отложенный поиск. Как это:
import * as dns from "dns";
import * as http from "http";
const url = new URL("http://localhost:8080");
const agent = new http.Agent({
lookup(hostname, options, callback) {
setTimeout(
() => dns.lookup(hostname, options, callback),
5 * 1000,
);
},
});
const request = http.request(url, {
timeout: 3 * 1000, // connect timeout
agent,
});
request.setTimeout(10 * 1000); // idle timeout
request.addListener("timeout", () => {
const message = !request.socket || request.socket.connecting ?
`connect timeout while connecting to ${url.href}` :
`idle timeout while connected to ${url.href}`;
request.destroy(new Error(message));
});
Удачного кодирования!
person
Elmer
schedule
06.07.2021