为Node.js HTTP请求发送/接收的字节数
一旦提供了HTTP请求,我想记录发送/接收的字节数。
这个数据的一个简单来源是req.connection.bytesRead
/ .bytesWritten
。但是,这对于HTTP 1.1保持活动连接是有问题的,因为相同的套接字可以用于多个请求。我需要记录每个请求,而不是每个连接。
解决方案必须在HTTP方面,但我没有看到记录的方法来获取我需要的数据。
为Node.js的http.Server
服务的HTTP请求计算读/写字节的正确方法是什么?
不幸的是,我从未找到适当的方法来做到这一点。我已经采取了一些相当可怕的鸭子冲孔,但它适用于我的特定用例。如果其他人偶然发现这个问题,你可以从这开始并从那里进行改进。
模块#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请求,如果你不小心,可能会导致你重复计算一些字节数。
为Node.js HTTP请求发送/接收的字节数
一旦提供了HTTP请求,我想记录发送/接收的字节数。
这个数据的一个简单来源是req.connection.bytesRead
/ .bytesWritten
。但是,这对于HTTP 1.1保持活动连接是有问题的,因为相同的套接字可以用于多个请求。我需要记录每个请求,而不是每个连接。
解决方案必须在HTTP方面,但我没有看到记录的方法来获取我需要的数据。
为Node.js的http.Server
服务的HTTP请求计算读/写字节的正确方法是什么?
不幸的是,我从未找到适当的方法来做到这一点。我已经采取了一些相当可怕的鸭子冲孔,但它适用于我的特定用例。如果其他人偶然发现这个问题,你可以从这开始并从那里进行改进。
模块#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请求,如果你不小心,可能会导致你重复计算一些字节数。