16

node.js を使用して、ファイルに書き込まれているデータをリアルタイムで読み取るための最善の方法を考え出す必要があります。問題は、ノードが動きの速い船であるため、問題に対処するための最善の方法を見つけるのが難しいことです。

やりたい
こと 何かを実行し、その結果をテキスト ファイルに書き込む Java プロセスがあります。通常、実行には 5 分から 5 時間かかり、その間ずっとデータが書き込まれ、かなり高いスループット レート (約 1000 行/秒) に達する可能性があります。

このファイルをリアルタイムで読み取り、ノードを使用してデータを集約し、クライアントでグラフ化できるソケットに書き込みます。

クライアント、グラフ、ソケット、および集計ロジックはすべて完了していますが、ファイルを読み取るための最善の方法について混乱しています。

私が試したこと (または少なくとも遊んだこと)
FIFO - Java プロセスに fifo に書き込み、ノードを使用してこれを読み取るように指示できます。これは実際、現在 Perl を使用してこれを実装している方法ですが、他のすべてはノードで実行されているためです。コードを移植することは理にかなっています。

Unix Sockets- 上記のように。

fs.watchFile-これは必要なものに機能しますか?

fs.createReadStream-これはwatchFileよりも優れていますか?

fs& tail -f- ハックのようです。

実際の
ところ、 Unix ソケットを使用する傾向がある私の質問は何ですか。これが最速のオプションのようです。しかし、ノードには、ファイルを fs からリアルタイムで読み取るためのより優れた組み込み機能がありますか?

4

4 に答える 4

9

システムがクラッシュしたり、実行中のプロセスのネットワーク内のメンバーの 1 人が死亡した場合にストリームが失われるのを防ぐために、データの永続的なストアとしてファイルを保持したい場合でも、ファイルへの書き込みと読み取りを続行できます。それから。

Java プロセスから生成された結果の永続的なストレージとしてこのファイルを必要としない場合は、Unix ソケットを使用する方が、使いやすさとパフォーマンスの両方の点ではるかに優れています。

fs.watchFile()ファイルシステムが報告するようにファイル統計で機能し、すでに書き込まれているファイルを読みたいので、これは必要なものではありません。

短い更新:fs.watchFile()前の段落でファイル統計を使用したことを非難していましたが、以下のコード例で自分自身でまったく同じことを行っていたことを認識して、非常に申し訳ありません! すでに読者に「気をつけて!」と警告していましたが。よくテストすることさえせずに、ほんの数分で書いたからです。fs.watch()それでも、代わりに使用するwatchFilefstatSync、基になるシステムがサポートしている場合は、より適切に実行できます。

ファイルからの読み取り/書き込みについて、休憩の楽しみのために以下に書きました。

test-fs-writer.js : [Java プロセスでファイルを書き込むため、これは必要ありません]

var fs = require('fs'),
    lineno=0;

var stream = fs.createWriteStream('test-read-write.txt', {flags:'a'});

stream.on('open', function() {
    console.log('Stream opened, will start writing in 2 secs');
    setInterval(function() { stream.write((++lineno)+' oi!\n'); }, 2000);
});

test-fs-reader.js : [注意してください。これは単なるデモンストレーションです。エラー オブジェクトをチェックしてください!]

var fs = require('fs'),
    bite_size = 256,
    readbytes = 0,
    file;

fs.open('test-read-write.txt', 'r', function(err, fd) { file = fd; readsome(); });

function readsome() {
    var stats = fs.fstatSync(file); // yes sometimes async does not make sense!
    if(stats.size<readbytes+1) {
        console.log('Hehe I am much faster than your writer..! I will sleep for a while, I deserve it!');
        setTimeout(readsome, 3000);
    }
    else {
        fs.read(file, new Buffer(bite_size), 0, bite_size, readbytes, processsome);
    }
}

function processsome(err, bytecount, buff) {
    console.log('Read', bytecount, 'and will process it now.');

    // Here we will process our incoming data:
        // Do whatever you need. Just be careful about not using beyond the bytecount in buff.
        console.log(buff.toString('utf-8', 0, bytecount));

    // So we continue reading from where we left:
    readbytes+=bytecount;
    process.nextTick(readsome);
}

安全に使用を避け、代わりに直接nextTick呼び出すことができます。readsome()ここではまだ同期作業を行っているため、まったく必要ありません。私はそれが好きです。:p

オリバーロイドによる編集

上記の例を取り上げますが、CSV データを読み取るように拡張すると、次のようになります。

var lastLineFeed,
    lineArray;
function processsome(err, bytecount, buff) {
    lastLineFeed = buff.toString('utf-8', 0, bytecount).lastIndexOf('\n');

    if(lastLineFeed > -1){

        // Split the buffer by line
        lineArray = buff.toString('utf-8', 0, bytecount).slice(0,lastLineFeed).split('\n');

        // Then split each line by comma
        for(i=0;i<lineArray.length;i++){
            // Add read rows to an array for use elsewhere
            valueArray.push(lineArray[i].split(','));
        }   

        // Set a new position to read from
        readbytes+=lastLineFeed+1;
    } else {
        // No complete lines were read
        readbytes+=bytecount;
    }
    process.nextTick(readFile);
}
于 2012-06-27T18:47:44.317 に答える
7

なぜtail -fハックだと思いますか?

考えているうちに、私は似たようなことをする良い例を見つけました。node.js と WebSocket を使用したリアルタイムのオンライン アクティビティ モニターの例:
http://blog.new-bamboo.co.uk/2009/12/7/real-time-online-activity-monitor-example-with-node-js -and-websocket

この回答を完成させるために、0.8.0 で実行されるサンプル コードを書きました (http サーバーはおそらくハックです)。

子プロセスは tail で実行されて生成されます。子プロセスは 3 つのストリームを持つ EventEmitter (この場合は stdout を使用) であるため、次のようにリスナーを追加するだけです。on

ファイル名: tailServer.js

利用方法:node tailServer /var/log/filename.log

var http = require("http");
var filename = process.argv[2];


if (!filename)
    return console.log("Usage: node tailServer filename");

var spawn = require('child_process').spawn;
var tail = spawn('tail', ['-f', filename]);

http.createServer(function (request, response) {
    console.log('request starting...');

    response.writeHead(200, {'Content-Type': 'text/plain' });

    tail.stdout.on('data', function (data) {
      response.write('' + data);                
    });
}).listen(8088);

console.log('Server running at http://127.0.0.1:8088/');
于 2012-06-27T18:05:14.540 に答える
1

このモジュールは、@hasanyasin が提案する原則の実装です。

https://github.com/felixge/node-growing-file

于 2012-07-05T00:12:20.627 に答える