完成后关闭流
Close stream when finished
我正在使用 fs.createReadStream(path).pipe(res);
使用 Express 流式传输 HTML 5 个视频,如果我刷新页面太多次(数千次),最终会导致错误 Error: EMFILE: too many open files
。我假设我需要执行某种清理并关闭文件以防止出现这种情况,但我不确定需要做什么。
每当用户寻找客户端尚未加载的视频部分时,我都会创建一个读取流,这使得这个问题会在几分钟内发生。任务管理器显示同一个文件打开了数百次,因此它似乎永远不会关闭。
流函数的相关部分:
fs.stat(path, function(err, stats) {
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
fs.createReadStream(path, {start: start, end: end}).pipe(res);
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
fs.createReadStream(path).pipe(res);
}
});
Linux/Unix EMFILE
问题已由 ulimit
解决。
我不确定 windows。
Google Windows ulimit EMFILE
进入这个 Stack Overflow
它说每个进程 2048 个文件描述符是 Windows 的限制。这符合你的说法
"in the thousands"
如果这个 2048 是一个固定的限制,我不确定它是否是,(你必须 google 来了解更多关于你的特定 OS 的信息)。
可能考虑将负载重新平衡到更多进程或更多服务器。
事实证明,流只会在到达末尾时被销毁并且文件会关闭 - 这种情况很少发生,因为您必须在不查找或关闭浏览器的情况下加载整个文件。
要解决此问题,您必须监听响应的关闭事件并销毁流:
res.on('close', function() {
stream.destroy();
});
有时关闭处理程序永远不会被调用,即使它被放在请求函数的第一行。我发现解决这个问题的一个相当老套的方法是在创建流之前检查套接字是否被破坏:
if (req.socket.destroyed) {
return;
}
固定流功能:
fs.stat(path, function(err, stats) {
if (req.socket.destroyed) {
return;
}
var stream;
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path, {start: start, end: end});
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path);
}
stream.pipe(res);
res.on('close', function() {
stream.destroy();
});
});
我正在使用 fs.createReadStream(path).pipe(res);
使用 Express 流式传输 HTML 5 个视频,如果我刷新页面太多次(数千次),最终会导致错误 Error: EMFILE: too many open files
。我假设我需要执行某种清理并关闭文件以防止出现这种情况,但我不确定需要做什么。
每当用户寻找客户端尚未加载的视频部分时,我都会创建一个读取流,这使得这个问题会在几分钟内发生。任务管理器显示同一个文件打开了数百次,因此它似乎永远不会关闭。
流函数的相关部分:
fs.stat(path, function(err, stats) {
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
fs.createReadStream(path, {start: start, end: end}).pipe(res);
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
fs.createReadStream(path).pipe(res);
}
});
Linux/Unix EMFILE
问题已由 ulimit
解决。
我不确定 windows。
Google Windows ulimit EMFILE
进入这个 Stack Overflow
它说每个进程 2048 个文件描述符是 Windows 的限制。这符合你的说法
"in the thousands"
如果这个 2048 是一个固定的限制,我不确定它是否是,(你必须 google 来了解更多关于你的特定 OS 的信息)。
可能考虑将负载重新平衡到更多进程或更多服务器。
事实证明,流只会在到达末尾时被销毁并且文件会关闭 - 这种情况很少发生,因为您必须在不查找或关闭浏览器的情况下加载整个文件。
要解决此问题,您必须监听响应的关闭事件并销毁流:
res.on('close', function() {
stream.destroy();
});
有时关闭处理程序永远不会被调用,即使它被放在请求函数的第一行。我发现解决这个问题的一个相当老套的方法是在创建流之前检查套接字是否被破坏:
if (req.socket.destroyed) {
return;
}
固定流功能:
fs.stat(path, function(err, stats) {
if (req.socket.destroyed) {
return;
}
var stream;
var size = stats.size;
var range = req.headers.range;
if (range) {
var parts = range.replace(/bytes=/, '').split('-');
var start = parseInt(parts[0]);
var end = parts[1] ? parseInt(parts[1]) : size - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + size,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path, {start: start, end: end});
} else {
res.writeHead(200, {
'Content-Length': size,
'Accept-Ranges': 'bytes',
'Content-Type': 'video/mp4'
});
stream = fs.createReadStream(path);
}
stream.pipe(res);
res.on('close', function() {
stream.destroy();
});
});