2015-11-21 32 views
13

Myユースケースは次のとおりです。 私のノードサーバーからパブリックAPIにたくさんの残りのAPI呼び出しを行います。時折レスポンスが大きくて、時には小さいです。私のユースケースでは、JSONの応答を文字列化する必要があります。応答がイベントループをブロックするため、大きなJSONを認識しています。いくつかの研究の後、child_process.forkを使用してこれらの応答を解析し、他のAPI呼び出しを待つ必要がないようにしました。私は、メインプロセスからforked child_processに大きな30 MBのJSONファイルを送信しようとしました。子プロセスがjsonを選択して解析するのに時間がかかります。子プロセスからの応答は巨大ではありません。私はちょうどストリングし、長さを取得し、メインプロセスに返信したい。Node.js - child_processに大きなオブジェクトを送信するのが遅い

マスターとチャイルドコードを添付します。

var moment = require('moment'); 
var fs = require('fs'); 
var process = require('child_process'); 
var request = require('request'); 

var start_time = moment.utc().valueOf(); 

request({url: 'http://localhost:9009/bigjson'}, function (err, resp, body) { 

    if (!err && resp.statusCode == 200) { 

    console.log('Body Length : ' + body.length); 

    var ls = process.fork("response_handler.js", 0); 

    ls.on('message', function (message) { 
     console.log(moment.utc().valueOf() - start_time); 
     console.log(message); 
    }); 
    ls.on('close', function (code) { 
     console.log('child process exited with code ' + code); 
    }); 
    ls.on('error', function (err) { 
     console.log('Error : ' + err); 
    }); 
    ls.on('exit', function (code, signal) { 
     console.log('Exit : code : ' + code + ' signal : ' + signal); 
    }); 
    } 
    ls.send({content: body}); 
}); 

response_handler.js

console.log("Process " + process.argv[2] + " at work "); 

process.on('message', function (json) { 
    console.log('Before Parsing'); 
    var x = JSON.stringify(json); 
    console.log('After Parsing'); 
    process.send({msg: 'Sending message from the child. total size is' + x.length}); 
}); 

やろうと何イム達成するためのより良い方法はありますか?一方で、私はnode.jsの力で毎秒1000回のAPI呼び出しを行う必要がありますが、時にはJSONのバックを取得してしまうこともあります。

+0

あなたのアプローチはうまくいくようです。あなたが「私のノードサーバー」と言うとき、私はそれがクライアントに役立つプロセスであると理解しています。あなたは本当にあなたのサーバーの内部からAPI呼び出しを行う必要がありますか?あなたはタスクを異なるプロセスに委任することはできませんし、それらとメッセージブローカーRedisのようなサーバーとの間の通信チャネルを設定することはできませんか?単にパイプやIPCの他の形式ですか? – kliron

+0

私は悪いですが、これをサーバーとして呼び出すためには、これをエージェントと見なすことができます。これは誰にも役立たない。このエージェントは、スケーラビリティの高いAPIクライアントとして機能します。 – Vinoth

+0

JSONを使って1つの大きなブロックでストリーミングするのではなく、ストリーミングJSONパーサーを使用することができます。 – mcfedr

答えて

3

あなたのタスクは、非同期性が役に立たないCPUバインド(30MBサイズのJSONの解析)だけでなく、ノードの非同期性が輝くIOバインド(30MBサイズのJSONの取得)のようです。

処理が多すぎるとすぐにリソースが枯渇し、パフォーマンスが低下します。 CPUバインドタスクの場合、コアを持つプロセスと同じだけ多くのプロセスが必要です。

N個の他のプロセスへのフェッチとデリゲート解析を実行するには、別々のプロセスを使用します(NはCPUコアの数から1を引いたもので、プロセス通信には何らかのIPC形式を使用します)。

一つの選択肢は、上記のすべてを編成するノードのクラスタモジュールを使用することです。このモジュールを使用してhttps://nodejs.org/docs/latest/api/cluster.html

、あなたはマスタープロセスが作成することができ、あなたの労働者は、先行処理したときにフォークに心配する必要はありません、作成するプロセスの数などがあります。IPCは通常どおりprocess.sendprocess.onで動作します。可能なワークフローは次のとおりです。

  1. アプリケーションの起動:マスタープロセスは、「フェッチャー」プロセスとN「パーサー」プロセスを作成します。
  2. fetcherが処理するAPIエンドポイントの作業リストが送信され、JSONをフェッチしてマスタプロセスに送り返します。
  3. すべてのJSONをフェッチし、マスターはパーサープロセスに送信します。ラウンドロビン方式でそれらを使用するか、パーサー作業キューが空であるか、または実行されていないときに、より高度なシグナリング方法をマスタプロセスに使用できます。
  4. パーサプロセスは、結果のJSONオブジェクトをmasterに送り返します。

特に、大きなオブジェクトを送受信するときは、IPCのオーバーヘッドが小さいことに注意してください。あなたは、フェッチャーにこれを回避する代わりに非常に小さな応答の解析を行うことさえできます。 「小」はおそらく< 32KBです。

も参照してください。Is it expensive/efficient to send data between processes in Node?

+0

これはまさに私がやろうとしていたものです。メインスレッドは、さまざまなAPIからすべてのコンテンツを取得し、別々のプロセスで処理する計算を行います。ここでの問題は、これらの新しいプロセスに応答を渡すことです。私は簡略化した例を与えました。ここでは、応答と同じくらい多くのプロセスを作成するように見えます。しかし、確かにそれをコアの数に制限する予定です。しかし、ノードクラスタによってどのように編成されるのか分からない。私がここに何かを逃しているかどうか教えてください。あなたは何か指針があれば、それを指摘してください。あなたの応答を感謝します。 – Vinoth

+0

@Vinoth答えを更新しました。クラスタのドキュメントを見てください。それはかなり簡単です。 – kliron

+0

これを試してください。ここでの仮定のように見えるのは、masterからのパーサーへの大きなjsonは、私の例ではchild_process.fork()を使用しているので、時間がかかりません。ノードクラスタは内部的にchild_process.fork()を使用しているので、どのように動作するのだろうと思います。病気を確認してください。応答を感謝します。 – Vinoth

関連する問題