在Node.js中附加多个gzip文件(同步)

时间:2014-08-04 14:45:43

标签: node.js gzip synchronous

我正在编写一个脚本,它可以读取大型日志文件,聚合它们,将聚合数据存储到mongo中,将详细数据存储到非常大量的小型gzip文件中。

我已经在Perl中实现了工作,我想知道在Node.js中这样做(对不起,不能透露Perl版本)。

虽然我已经能够实现解析,聚合和存储到mongo中,但我仍然对“存储大量小gzip文件”感到困惑。

导入过程:

  1. logReader实例在异步中读取/解析单个日志文件并且不时发出data事件(暂停读取流并等待恢复调用),当达到EOF时end
  2. import实例侦听data发出的logReader事件(现在我需要以同步方式将详细数据放入小gzip文件中,然后恢复logReader)
  3. end上将剩余的内容存储在步骤2中。聚合文档存储在mongo中(mongo存储已使用批量操作和标准mongo驱动程序完成)
  4. import个实例会有多个进程执行此作业,并且在尝试编写文件时可能会发生冲突(因此我需要通过fs-ext使用flock。)

    假设导入实例位于logReader data事件回调中(步骤2):

    • 我需要编写(创建或附加!)几千个gzip文件,每个文件:
      • 以附加模式打开精确位置的gzip文件
      • 使用独占锁定锁定文件
      • 寻求结束(也知道那里是否有任何数据 - 对于我想存储标题的空文件)
      • 创建gzip转换流,它应该输入到已打开的文件中(我不确定它是否能在Node.js中正常工作 - 在Perl中我这样做时指定了'Append'选项)
      • 将数据写入gzip流
      • 返回有关写入的行的信息以及对“for each file”循环所花费的时间

    以下简化代码:

    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 - 因此,我会感谢提示/建议/最佳实践如何实现我想要做的事情。

2 个答案:

答案 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)压缩字符串。