我正在编写一个脚本,它可以读取大型日志文件,聚合它们,将聚合数据存储到mongo中,将详细数据存储到非常大量的小型gzip文件中。
我已经在Perl中实现了工作,我想知道在Node.js中这样做(对不起,不能透露Perl版本)。
虽然我已经能够实现解析,聚合和存储到mongo中,但我仍然对“存储大量小gzip文件”感到困惑。
导入过程:
logReader
实例在异步中读取/解析单个日志文件并且不时发出data
事件(暂停读取流并等待恢复调用),当达到EOF时end
import
实例侦听data
发出的logReader
事件(现在我需要以同步方式将详细数据放入小gzip文件中,然后恢复logReader)end
上将剩余的内容存储在步骤2中。聚合文档存储在mongo中(mongo存储已使用批量操作和标准mongo驱动程序完成) import
个实例会有多个进程执行此作业,并且在尝试编写文件时可能会发生冲突(因此我需要通过fs-ext使用flock。)
假设导入实例位于logReader data
事件回调中(步骤2):
以下简化代码:
var fs = require('fs-ext'),
deasync = require('deasync'),
zlib = require('zlib');
IndexedFs.prototype.write = function(path, data) {
var io, pos, t = new Date();
io = fs.createWriteStream(path, {flags: 'a'});
while (io.fd === null) { deasync.runLoopOnce(); }
try {
fs.flockSync(io.fd, 'ex');
} catch (e) {
console.log("Failed to lock file '%s':\n %s", path, e);
io.end();
return false;
}
try {
pos = fs.seekSync(io.fd, 0, 2); // seek to end
} catch (e) {
console.log("Failed to seek end in file '%s':\n %s", path, e);
io.end();
return false;
}
io = zlib.createGzip().pipe(io);
if (pos === 0) { io.write(__HEADER.join("\t") + "\n"); }
count = _writeData(io, data); // this just serializes and does io.write(...)
io.end();
return [count, new Date() - t];
};
我需要将上面的函数设置为“同步”(我想要阻止整个过程)并返回有关写入的行和时间的信息。
我找到deasync
,这有助于我在调用createWriteStream()
后等待文件实际打开。写作有效,但文件没有被压缩(所以我甚至不知道附加是否有效)。
我理解zlib in Node.js is async only - 因此,我会感谢提示/建议/最佳实践如何实现我想要做的事情。
答案 0 :(得分:1)
节点0.12.0(可能更早)提供这些呼叫的同步版本:
http://nodejs.org/docs/v0.12.0/api/zlib.html#zlib_convenience_methods
// Compress w/ Zip
var zipData = zlib.gzipSync(json);
答案 1 :(得分:0)
最后,我以异步方式实现了这一点并使用了queue-async模块。
gzip附加有效但读取仅解压缩第一个gzip块(issue),因此我必须打开,读取,解压缩,打包更新的字符串并写入。
来自zlib documentation的不太清楚 - 我希望:
io = zlib.createGzip().pipe(fs.createWriteStream(...));
io.write(string);
工作,但它没有 - 我不得不使用zlib.gzip("somestring", callback)
压缩字符串。