2013-08-03 2 views
6

Node.js非同期並列 - 結果は何ですか?コードがある

async.series(tasks, function (err) { 
    return callback ({message: 'tasks execution error', error: err}); 
}); 

tasksは、その各々がHTTPリクエスト(requestモジュールを使用)、(MongoHQインスタンスに)データを格納するためにMongoDBのAPIを呼び出すをpeforms関数の配列です。私の現在の入力、(〜200タスクが実行する)で

、それは

[normal mode] collection cycle: 1356.843 sec. (22.61405 mins.) 

をとる。しかし、単純にparallelからseriesからの変更をしようと、それは壮大な利益を与えます。 ~23 minsではなく、~30 secsでほぼ同じ量のタスクが実行されます。

しかし、何も無料であることを知って、私はその変化の結果を理解しようとしていますか?開いているソケットの数がはるかに多く、メモリ消費量が多く、DBサーバーに多くの負荷がかかることは分かりますか?

私はコードを実行するマシンは1GBのRAM Ubuntuなので、私はそのアプリケーションが一度だけハングアップするので、リソースが足りないことが原因ですか?

+1

パフォーマンスを向上させるには、おそらく 'async.parallelLimit(array、limit、cb)'を調整して使用するべきです。実行をオーバーフローさせない並列実行の制限を見つけると、async.parallelより速くなります:Pボーナスとして、もうハングしません:) – randunel

答えて

5

あなたの直感は正しいですが、並列性は無料ではありませんが、確かにそれを支払うことができるかもしれません。

nodeloadのような負荷テストモジュール(またはモジュールの集まり)を使用すると、この並列処理がサーバーにどのように影響しているかを定量化して、許容可能かどうかを判断できます。

Async.parallelLimitは、必要に応じてサーバーの負荷を制限する良い方法ですが、まず制限が必要な場合はが重要です。明示的にテストすることは、システムの限界を知る最良の方法です(eachLimitは異なる署名がありますが、同様に使用できます)。

これ以外にも、async.parallelを使用する一般的な落とし穴には、その機能よりも複雑な制御フローが必要です(あなたの説明には当てはまりません)。多くのファイルを記述している場合は、システムのファイル記述子の制限にぶつかります)。あなたの200件のリクエストと1GB RAMの保存操作では、イベントハンドラでたくさんのマッサージをしていない限り、うまくいくと思いますが、サーバーがハングしている場合は、parallelLimitを使用すると良いでしょう。

また、これらのことを理解するには、テストが最適です。

+0

アプリケーションの24-30時間の作業後にサーバーがハングすることがありますシリアル実行でも)、アプリを再起動する方法は1つだけです。メモリ不足か何か(エラーはありませんが、httpリクエストはハングアップします)のためです。 –

+0

これは、私に過負荷のサーバーよりもメモリリークのように聞こえます。 24-30時間ごとに200タスクサイクルを実行する頻度はどのくらいですか? – Wyatt

+0

非常に頻繁に、最大100回..私はまた、メモリリークが疑わしいが、それに取り組むのは難しい。 –

0

主な欠点は、データベースサーバーの負荷が急上昇していることです。それはあなたの設定によっては大丈夫かもしれません。

データベースサーバーが共有リソースの場合は、代わりにasync.eachLimitを使用してパラレル要求を制限することをお勧めします。

3

Iはasync.parallelが複数の機能を実行することを指摘するであろう同時にない(完全に)並列。それは仮想並列性によく似ています。

同時実行は、マルチタスク/スケジューリングを使用して、単一のCPUコアで異なるプログラムを実行するようなものです。真の並列実行は、マルチコアCPUの各コアで異なるプログラムを実行することになります。これはノードとして重要です。jsはシングルスレッドアーキテクチャを持っています。

ノードに関する最も良い点は、I/Oについて心配する必要がないことです。非常に効率的にI/Oを処理します。

あなたの場合、MongoDBにデータを格納していますが、主にI/Oです。したがって、それらを並列に実行すると、ネットワーク帯域幅が使い果たされ、ディスクから読み書きするとディスクの帯域幅にもなります。あなたのサーバーは、CPUの過負荷のためにハングしません。


この結果、サーバーに負荷がかかると、リクエストが失敗する可能性があります。 EMFILEエラー(開いているファイルが多すぎます)が表示されることがあります。各ソケットはファイルとしてカウントされます。通常、接続はプールされます。つまり、ソケットがプールから選択された接続を確立し、完了したらプールに戻ります。 ulimit -n xxxxでファイル記述子を増やすことができます。

ECONNRESET(エラー:ソケットがハングアップする)、ECONNREFUSEDまたはETIMEDOUTのように過負荷になると、ソケットエラーが発生することがあります。だから適切に処理してください。また、mongoDBサーバーの最大同時接続数も確認してください。


最後に、ガベージコレクションのためにサーバーがハングアップする可能性があります。メモリが一定のポイントまで増加した後、ガベージコレクションが開始され、しばらくしてから定期的に実行されます。最大ヒープメモリV8の容量は約1.5 GBです。したがって、メモリが高い場合はGCが頻繁に実行されることを期待してください。その制限より多くを要求すると、ノードはprocess out of memoryでクラッシュします。したがって、あなたのプログラムでメモリリークを修正してください。これらを見ることができますtools

0

複数のユーザーが接続する場合は、差額を実現します:

この場合には、プロセッサが相対複数のユーザーのいくつかの操作を実行しようと非同期複数の操作

を扱うことができます等しい

T = task 
U = user 
(T1.U1 = task 1 of user 1) 

T1.U1 => T1.U2 => T2.U1 => T8.U3 => T2.U2 => etc 

これはアトミックなものです(特別なDB操作では、アトミックを見てみましょう)。

so m使用する方が速いaybe:

T2.U1 before T1.U1 

- これはコールバックを使用することにより予防です/またはそのためのコールバック

ている...これは何であると思います -

T2.U1 is based on T1.U1 

がするまで、これは問題ありませんあなたは知りたがっています...少し遅れました

関連する問題