LINUX.ORG.RU

http сервер на ноде

 , , , ,


0

3

Проблема в завершении запросов по таймауту Service Unavailable 503. В nginx просто решалось - запрос завершился - убился дочерний процесс со всеми потрохами (запросы к БД, сетевые, ресурсы и т. д.). В ноде, конкретнее в express, так не получится, там не создается отдельный процесс для каждого запроса. Промайсы тоже тривиально не отменяются, это нужно в каждом запросы пасти статус request\response и обрабатывать - геморойно, не вариант. Можно отменить сам запрос и отдать клиенту ошибку, но сам запрос асинхронный на сервере будет продолжать работу и после того как он просрется - выдаст ответ на завершенный http-запрос - в пустоту - зря получается пахал столько время

Варианты:

* Забить, но завершать сам http-запрос

* Забить полностью, не завершать http-запрос, не устанавливать таймауты и делегировать вопросы по времени каждому отдельному обработчику запросов. Тут опасаюсь ошибок в самих обработчиках, где-то может просмотришь, и будет он вечно висеть, накапливаться со временем, тем самым будет утечка памяти

* запускать в отдельном процессе каждый http запрос. Вариант интересный, но не встречал реализаций

Что посоветуете?

★★★★

В nginx просто решалось - запрос завершился - убился дочерний процесс со всеми потрохами (запросы к БД, сетевые, ресурсы и т. д.). В ноде, конкретнее в express, так не получится, там не создается отдельный процесс для каждого запроса.

Как тебе удаётся сравнивать реверс-прокси сервер с http-фреймворком?

annulen ★★★★★
()

в express.js. можно так

const express = require('express');

const app = express();

app.use((req, res, next) => {
    // Устанавливаем таймаут в 5 секунд
    req.setTimeout(5000, () => {
        req.destroy(new Error('Request timeout'));
    });
    next();
});

app.get('/long-request', async (req, res) => {
    // Симуляция долгого запроса
    await new Promise(resolve => setTimeout(resolve, 10000));
    res.send('This should not be reached');
});

// Глобальный обработчик ошибок
app.use((err, req, res, next) => {
    if (err.message === 'Request timeout') {
        return res.status(408).json({ error: 'Request timeout' });
    }
    next(err);
});

app.listen(3000, () => console.log('Server running on port 3000'));

и этот timeout должен быть равен timeout nginx-а

romanlinux ★★★
()
Последнее исправление: romanlinux (всего исправлений: 1)

nginx никакие сторонние процессы не трогает, не пиши чушь.

А nodejs-мусор выкинь, ничего хорошего ты там не найдёшь.

запускать в отдельном процессе каждый http запрос. Вариант интересный, но не встречал реализаций

Это техника из 90-х, а nodejs-юзеры до неё сейчас дорастают, круто. Повторяю, выкинь этот мусор и забудь.

firkax ★★★★★
()
Ответ на: комментарий от firkax

nginx никакие сторонние процессы не трогает, не пиши чушь.

да, не совсем корректно написал, процессы не трогает сам, но делегирует это например через FastCGI, но я nginx взял в качестве примера, это не принципиально, можно Апач взять, он процессы запускает напрямую например

Это техника из 90-х, а nodejs-юзеры до неё сейчас дорастают, круто. Повторяю, выкинь этот мусор и забудь.

Ну а как иначе, брат? Просто тупо взять и обрубить запрос со всеми потрохами? Процессы запускать тоже не просто и тяжело по скорости и взаимодействия, это убьет все преимущества ноды. Палка о 2х концах получается

gobot ★★★★
() автор топика

а не пробовали для начала определить в каком именно месте js-кода таймаут происходит? Оптимизированы ли запросы к базе, нет ли хождений по внешним урлам прямо из контроллера-обрабочитка, число-дробилки? Дело в то, что нода она про ооочень быстро обработать и быстро отдать ответ, все тяжелые запросы должны улетать воркерам

fpastush
()
Последнее исправление: fpastush (всего исправлений: 1)

Можно придумать костыль (в ноде все является костылем в той или иной степени) типа context.Context в го. Может погугли по таким словам как cancellation token nodejs

nikolnik ★★★
()