Почему HTTP-сервер NodeJS закрывает сокет по таймауту без ответа? - PullRequest
0 голосов
/ 08 мая 2020

Учитывая NodeJS http-сервер с таймаутом в 10 секунд:

const httpServer = require('http').createServer(app);
httpServer.timeout = 10 * 1000;

По таймауту Почтальон показывает это без кода ответа:

Error: socket hang up
Warning: This request did not get sent completely and might not have all the required system headers

Если NodeJS сервер находится за обратным прокси nginx, nginx возвращает ответ 502 (upstream prematurely closed connection while reading response header from upstream). Но здесь это просто NodeJS / express, работающий на локальном хосте. Тем не менее, можно было бы ожидать правильного ответа http.

Согласно этот ответ , это ожидаемое поведение, сокет просто уничтожается.

В архитектуре с nginx обратный прокси-сервер, обычно сервер просто уничтожает сокет, не отправляя ответ на тайм-аут прокси?

1 Ответ

2 голосов
/ 08 мая 2020

Вы устанавливаете тайм-аут сокета , когда устанавливаете тайм-аут HTTP-сервера . Тайм-аут сокета предотвращает злоупотребления со стороны клиентов, которые могут захотеть повесить ваше соединение с вами DOS. У него есть и другие преимущества, такие как обеспечение определенного уровня обслуживания (хотя они часто более важны, когда вы являетесь клиентом).

Причина, по которой он использует тайм-аут сокета вместо отправки кода состояния 408 (Запрос Тайм-аут), потому что код состояния, возможно, уже был отправлен для успешного сообщения.

Если вы хотите реализовать тайм-аут ответа на своем бэкэнде и аккуратно обработать его, вы можете тайм-аут ответа самостоятельно. Обратите внимание, что вам, скорее всего, следует вместо этого ответить 408. 502 для шлюзов, таких как прокси-серверы http (nginx), чтобы указать, что нисходящее соединение не удалось.

Вот простая реализация решения этой проблемы.

const httpServer = require('http').createServer((req, res) => {
    setTimeout(()=>{
        res.statusCode = 200;
        res.statusMessage = "Ok";
        res.end("Done"); // I'm never called because the timeout will be called instead;
    }, 10000)
});

httpServer.on('request', (req, res) => {
    setTimeout(()=>{
        res.statusCode = 408;
        res.statusMessage = 'Request Timeout';
        res.end();
    }, 1000)
});

httpServer.listen(8080);
...