Байты, отправленные/полученные для запроса Node.js HTTP - программирование
Подтвердить что ты не робот

Байты, отправленные/полученные для запроса Node.js HTTP

Как только HTTP-запрос был подан, я хотел бы зарегистрировать количество отправленных/полученных байт.

Простым источником для этих данных является req.connection.bytesRead/.bytesWritten. Тем не менее, это является проблемой для HTTP 1.1 keep-alive соединений, поскольку один и тот же сокет может использоваться для нескольких запросов. Мне нужно регистрировать запрос, а не за соединение.

Решение должно лежать на HTTP-стороне вещей, но я не вижу никаких методов, документированных для получения необходимых мне данных.

Каков правильный способ вычисления байтов, считанных/записанных для HTTP-запросов, обслуживаемых Node.js http.Server?

4b9b3361

Ответ 1

К сожалению, я никогда не нашел подходящего способа сделать это. Я прибегал к довольно ужасной утиной, но это работает для моего конкретного случая использования. Если кто-то еще споткнется вместе с этой проблемой, вы можете начать с этого и уточнить оттуда.

Модуль №1: "Дополнительные события"

Все, что делает этот модуль, это заставить объект ответа испускать событие finishBeforeSocketDestroy. Поскольку мне понадобилось это событие в нескольких местах в моем приложении, я фактически сделал отдельный модуль только для этого утиного пунша. app.use() до модуля № 2.

module.exports = function (req, res, next) {
    var end = res.end;

    res.end = function () {
        res.end = end;
        res.emit('finishBeforeSocketDestroy');
        res.end.apply(this, arguments);
    }

    next();
}

Модуль №2: "Статистика"

Этот модуль создает объект req.stats, содержащий всевозможные полезные свойства для отслеживания использования полосы пропускания во время использования соединения и после его завершения.

var pollTime = 1000;
module.exports = function (req, res, next) {
    var pollInterval;

    function pollStats () {
        if (typeof req.stats._lastMeasuredTime === 'object') {
            var secondsSinceLastMeasurement = ((new Date() - req.stats._lastMeasuredTime) / 1000);
            req.stats.averageRate = {
                read: (req.socket.bytesRead - req.stats.bytesRead) / secondsSinceLastMeasurement,
                write: (req.socket.bytesWritten - req.stats.bytesWritten) / secondsSinceLastMeasurement
            };
        }
        req.stats._lastMeasuredTime = new Date();
        req.stats.bytesRead = req.socket.bytesRead;
        req.stats.bytesWritten = req.socket.bytesWritten;
    }

    req.stats = {
        startTime: new Date(),
        endTime: null,
        averageRate: {read: null, write: null},
        bytesRead: req.socket.bytesRead,
        bytesWritten: req.socket.bytesWritten,
        _lastMeasuredTime: new Date()
    };

    pollInterval = setInterval(pollStats, pollTime);

    res.on('finishBeforeSocketDestroy', function () {
        clearInterval(pollInterval);
        pollStats();
        req.stats.endTime = new Date();
    });

    next();
}

Как я сказал... беспорядочно. Я только отправляю его, так как утиная перфорация может быть вашим единственным вариантом. Также будьте осторожны, что socket может повторно использоваться для нескольких HTTP-запросов, что может привести к двойному подсчету нескольких байтов, если вы не будете осторожны.

Ответ 2

Просто сохраните значение трафика после каждого ответа и вычислите разницу в обработчике "finish" или "end":

// server.onRequest:
  ...
  req._prevBytesWritten = 0;

// response.onFinish/onEnd:
  ...
  responseLen = req.socket.bytesWritten - req._prevBytesWritten;
  req._prevBytesWritten = req.socket.bytesWritten;