232

私はNode.jsHTTPサーバーをいじり始めて、サーバー側のJavascriptを書くのが本当に好きですが、何かが原因で、WebアプリケーションにNode.jsを使い始めることができません。

非同期I/Oの概念全体を理解していますが、画像操作や大きなデータセットの並べ替えなど、手続き型コードがCPUを非常に集中的に使用するエッジケースについては少し心配しています。

私が理解しているように、サーバーは、ユーザーのリストの表示やブログ投稿の表示などの単純なWebページ要求に対して非常に高速になります。ただし、グラフィックを生成したり、数千の画像のサイズを変更したりする非常にCPUを集中的に使用するコード(たとえば、管理バックエンド)を記述したい場合、要求は非常に遅くなります(数秒)。このコードは非同期ではないため、これらの数秒間にサーバーに着信するすべてのリクエストは、遅いリクエストが完了するまでブロックされます。

1つの提案は、CPUを集中的に使用するタスクにWebワーカーを使用することでした。ただし、Webワーカーは、別のJSファイルを含めることで機能するため、クリーンなコードを作成するのが難しくなるのではないかと心配しています。CPUを集中的に使用するコードがオブジェクトのメソッドにある場合はどうなりますか?CPUを集中的に使用するすべてのメソッドに対してJSファイルを作成するのはちょっと面倒です。

もう1つの提案は、子プロセスを生成することでしたが、それではコードの保守性がさらに低下します。

この(知覚された)障害を克服するための提案はありますか?CPUの重いタスクが非同期で実行されることを確認しながら、Node.jsを使用してクリーンなオブジェクト指向コードをどのように記述しますか?

4

5 に答える 5

303

これは、Webサーバーの定義の誤解です。これは、クライアントと「対話」するためにのみ使用する必要があります。負荷の高いタスクはスタンドアロンプ​​ログラムに委任する必要があります(もちろん、JSで作成することもできます)。
おそらく汚れていると言うかもしれませんが、画像のサイズ変更でスタックしているWebサーバープロセスはさらに悪いです(他のクエリをブロックしない場合でも、Apacheなど)。それでも、コードの冗長性を回避するために共通ライブラリを使用することができます。

編集:私はアナロジーを思いついた。Webアプリケーションはレストランとして使用する必要があります。あなたにはウェイター(ウェブサーバー)と料理人(労働者)がいます。ウェイターはクライアントと連絡を取り、メニューの提供や料理がベジタリアンかどうかの説明などの簡単なタスクを実行します。一方、彼らはより難しい仕事を台所に委任します。ウェイターは単純なことしかしていないので、迅速に対応し、料理人は仕事に集中できます。

ここでのNode.jsは、一度に多くのリクエストを処理できる単一の非常に才能のあるウェイターであり、Apacheは、それぞれ1つのリクエストを処理するだけの愚かなウェイターのギャングです。この1人のNode.jsウェイターが料理を始めた場合、それは即座の大惨事になります。それでも、料理は、キッチンの混乱や応答性の漸進的な低下は言うまでもなく、Apacheウェイターの大量の供給さえも使い果たす可能性があります。

于 2010-08-16T09:25:02.573 に答える
60

必要なのはタスクキューです!長時間実行するタスクをWebサーバーから移動することは良いことです。各タスクを「個別の」jsファイルに保持すると、モジュール性とコードの再利用が促進されます。長期的にデバッグと保守が容易になるようにプログラムを構造化する方法を考える必要があります。タスクキューのもう1つの利点は、ワーカーを別の言語で記述できることです。タスクをポップして作業を行い、応答を書き戻すだけです。

このようなものhttps://github.com/resque/resque

これは、なぜ彼らがそれを構築したのかについてのgithubからの記事ですhttp://github.com/blog/542-introducing-resque

于 2010-08-21T03:39:55.937 に答える
24

CPUを集中的に使用するコードで非同期を実行するのではなく、並列で実行する必要があります。HTTPリクエストを処理しているスレッドから処理作業を取得する必要があります。これがこの問題を解決する唯一の方法です。NodeJSの場合、答えはクラスターモジュールです。、子プロセスを生成して重労働を行うため。(AFAIKノードにはスレッド/共有メモリの概念はありません。プロセスか何もありません)。アプリケーションの構造には2つのオプションがあります。8つのHTTPサーバーを生成し、子プロセスで計算集約型のタスクを同期的に処理することで、80/20ソリューションを取得できます。それを行うのはかなり簡単です。あなたはそのリンクでそれについて読むのに1時間かかるかもしれません。実際、そのリンクの上部にあるサンプルコードを削除するだけで、そこまでの道のりは95%になります。

これを構造化するもう1つの方法は、ジョブキューを設定し、キューを介して大きな計算タスクを送信することです。ジョブキューのIPCには多くのオーバーヘッドが関連付けられているため、これは、タスクがオーバーヘッドよりもかなり大きい場合にのみ役立つことに注意してください。

これらの他の答えのどれもクラスターについて言及していないことに私は驚いています。

背景:非同期コードは、どこか別の場所で何かが発生するまで中断するコードであり、その時点でコードはウェイクアップして実行を継続します。何か遅いことがどこかで起こらなければならない非常に一般的なケースの1つは、I/Oです。

非同期コードは、作業を行うのがプロセッサである場合は役に立ちません。これはまさに「計算集約型」タスクの場合です。

さて、非同期コードはニッチに見えるかもしれませんが、実際には非常に一般的です。たまたま、計算集約型のタスクには役立ちません。

I / Oの待機は、たとえばWebサーバーで常に発生するパターンです。サーバーに接続するすべてのクライアントはソケットを取得します。ほとんどの場合、ソケットは空です。ソケットがデータを受信するまで何もしたくありません。データを受信した時点で、要求を処理します。内部的には、NodeのようなHTTPサーバーは、イベントライブラリ(libev)を使用して、開いている何千ものソケットを追跡しています。OSはlibevに通知し、ソケットの1つがデータを取得するとlibevはNodeJSに通知し、NodeJSはイベントをイベントキューに入れます。この時点でhttpコードが開始され、イベントが次々に処理されます。ソケットにデータが含まれるまでイベントはキューに入れられないため、イベントがデータを待機することはありません。イベントはすでに存在しています。

シングルスレッドのイベントベースのWebサーバーは、ボトルネックがほとんど空のソケット接続の束を待っていて、アイドル状態の接続ごとにスレッド全体またはプロセスを必要とせず、250kをポーリングしたくない場合のパラダイムとして意味があります。データがある次のソケットを見つけるためのソケット。

于 2017-02-21T05:21:32.967 に答える
7

使用できるアプローチのカップル。

@Timが指摘しているように、メインのサービングロジックの外部または並列に配置される非同期タスクを作成できます。正確な要件によって異なりますが、cronでさえキューイングメカニズムとして機能できます。

WebWorkersは非同期プロセスで動作できますが、現在node.jsではサポートされていません。サポートを提供する拡張機能がいくつかあります。例:http://github.com/cramforce/node-worker

それでも、標準の「requires」メカニズムを介してモジュールとコードを再利用できます。ワーカーへの最初のディスパッチが、結果の処理に必要なすべての情報を渡すことを確認する必要があります。

于 2010-08-23T04:29:28.667 に答える
0

使用child_processは1つの解決策です。ただし、生成された各子プロセスは、Goと比較して多くのメモリを消費する可能性がありますgoroutines

kueなどのキューベースのソリューションを使用することもできます

于 2018-06-20T10:27:21.260 に答える