2016-10-17 14 views
3

処理に約5〜10分かかるAPIコールがあります。タイムアウトメソッドを設定して、キューに入れられた状態の即時API応答を取得します。長時間実行中のエクスプレスAPIプロセスを別のスレッドで実行するNodeJs

doWork(object) => { /*... Takes 5 minutes */ } 

app.post('/longProcess',(req,res)=> { 
    setTimeout(this.doWork(req.body), 1000); 
    res.send({ status: 'queued' }); 
}) 

以下、視覚

シンプルこれは、即時応答を与える最初の要求のために動作します。しかし、第2の要求はdoWorkが終了するのを待ってロックされます。

SetTimeoutを使用する代わりに、私が実際にやりたいことは、longProcessを1つずつキューに入れて処理する個別のシングルスレッドに送信することです。

提案がありますか?

+1

[私のポスト](http://stackoverflow.com/questions/40085654/run-long-running-express-api-process-in-seperate-thread-nodejs/40088309#40088309)はあなたの質問に答えましたか?それは、あなたが考えるかもしれなかった場合は、[答えを受け入れる](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235)今、他の人が探しているのでこの問題は、あなたの質問には良い答えがなく、読むことができないことがあります。それがあなたの質問に答えなかったなら、何が欠けているかについてコメントしてください。私は古い答えを見ています。改善が必要な場合は、それらの内容を更新したいと考えています。ありがとう。 – rsp

答えて

8

問題

は問題がdoWork()は多くの時間がかかりますが、その生涯にとって明らかにブロックあなたのスレッドということとイベントループを実行するための任意のチャンスを得ないということではありません。

考えられる原因

これは、いくつかのことが原因で発生することができ、あなたがdoWork()のソースを表示したりしても、それが何を説明し、どのようにしませんでしたので、私はここでしか推測することができます。たとえば:

  • あなたdoWork()は、自分の名前でSyncfs.readFileSync()または他の機能のようなブロック操作を使用することができます。
  • doWork()にはforまたはwhileループがあり、5〜10分間回転し、イベントループをブロックします。
  • あなたのコードは、それらのステップ間でイベントループを繰り返すために、ステップに分割されていない深刻な番号のクランチを行います。

一般に、doWork()は、メインスレッドをブロックしない場合には数時間かかることがあり、ミリ秒間でも他の接続が停止されることはありません。 、実行時間の長いループとされている重い計算を、その問題への最も簡単な解決策は、ブロッキング関数呼び出し(Sync接尾たり、独自の機能を持つもの)を回避することができ

スレッドをブロック

ソリューション

ストップ短いステップに分割されません。例について

  • の代わりに使用してreadFile()
  • 代わり長い走行readFileSync()使用ループしながら、非常に深い再帰の代わりに(TCOの可能性のおかげで)process.nextTick()
  • を使用するために/、ループを使用部分に分けてprocess.nextTick()

上記の解決策が適用できない場合(私は方法がない私はあなたのdoWork()関数について何も知らないので教えてください)、別の方法をとることもできます。あなたができることがいくつかあります。別の解決策は、異なるプロセスにあなたが長時間実行されるタスクを起動するたびに出現するchild_processを使用することです

スポーンプロセス

。子供が仕事を終えてそれに応じて反応したときにあなたのメインプロセスに通知することができますが、待っている間はブロックされません。参照:https://nodejs.org/api/child_process.html

あなたはまた、唯一の新しいタスクをスケジュールし、それらを行うか、それらを待たないでしょう、あなたのメインプログラムに影響を与えずに、他のプロセスによってそれらを保留中のジョブのキューを使用して処理できるキューを使用します。通常、Redisで実行されるようなキューがありますが、CouchDBまたはMongoDBでも実行できます。あなたは、あなたのワーカープロセスがそれを取ることができる保留中のタスクのいくつかの中央レジストリを持つ必要があります。

お客様のニーズに最も適したモジュールを確認するには、これらのモジュールのドキュメントをご覧ください。

関連する問題