2016-11-05 5 views
2

だから、私は他の言語で長い時間からJS/Nodeの方法を学んでいます。単純なノードredisループ(ioredisを使用)を書く方が良いですか?

私はredisチャネルから読み込み、一時的にそれをワーキングチャネルに保存し、作業を行い、それを除去し、移動する小さなマイクロサービスを持っています。チャンネルにもっと多くのものがある場合、すぐに再実行されます。そうでない場合は、タイムアウトを設定し、1秒後に再度チェックします。

これはうまくいきますが、タイムアウトポーリングはこれに近づく「正しい」方法ではないようです。そして、私は、RPOPLPUSHに対してブロックしようとすると、Node ....やその他のオプションで待機するためにBRPOPLPUSHを使用することについて多くを見いだせませんでした。 (パブ/サブはこれが唯一のリスナーです...ここにオプションではありません、そしてそれは常に聞いてすることはできません。)

は、ここで私がやっているの短い本質です:

var Redis = require('ioredis'); 
var redis = new Redis(); 

var redisLoop = function() { 
    redis.rpoplpush('channel', 'channel-working').then(function (result) { 
     if (result) { 
      processJob(result); //do stuff 

      //delete the item from the working channel, and check for another item 
      redis.lrem('channel-working', 1, result).then(function (result) { }); 
      redisLoop(); 
     } else { 
      //no items, wait 1 second and try again 
      setTimeout(redisLoop, 1000); 
     } 
    }); 
}; 

redisLoop(); 

私は本当に明白な何かを見逃しているように感じる。ありがとう!

+0

pub/subがオプションではない理由を詳しく説明できますか?購読しているリスナーがいないときは、公開するのが大丈夫です。あなたはRedisに仕事を送るプロセスを公開することもできます。このアプリが購読されている場合、それは目を覚ますでしょう。そうでない場合、何も起こりません。 –

+0

メッセージがサブスクライバなしで公開されている場合、より複雑な回避策なしで見たことから、メッセージは失われます。これはメッセージキューモデルのほうが多く、リスナーは1つだけです。チャンネル内のアイテムは、ポップされるまで永遠に座っていることが最も重要です。数秒または数日(プロセスが終了するとマシンがオフラインになるなど)です。 – XediDC

+0

それは本当です、メッセージは失われます。だからあなたも*公開しています。仕事を生成するアプリケーションは仕事を待ち行列に入れて、何か(例えば空の文字列)を 'PUBLISH 'して、このアプリがオンラインでもスリープ状態になっても起きるようにします。 –

答えて

2

BRPOPLPUSHノードにクライアント、それをブロックしていません。この例では、あなたがポーリングを取り除くために必要なものだと私は思っています。あなたがあなたの次のダニは、アイテムが正常にchannel-workingから削除された後にのみ実行されることを保証するためにlrem(...).then(redisLoop)を使用する必要がありますのでredis.lremは、非同期であることを

var Redis = require('ioredis'); 
var redis = new Redis(); 

var redisLoop = function() { 
    redis.brpoplpush('channel', 'channel-working', 0).then(function (result) { 
     // because we are using BRPOPLPUSH, the client promise will not resolve 
     // until a 'result' becomes available 
     processJob(result); 

     // delete the item from the working channel, and check for another item 
     redis.lrem('channel-working', 1, result).then(redisLoop); 
    }); 
}; 

redisLoop(); 

注意。

+0

ありがとうございます!私はそれに近づくかもしれないと思う....しかし、私がそこに着く前に別の方向に行った。私のトリミングされた例を見て、あなたが書いたことを今見ているのは本当に明白です。 :) – XediDC

+0

うん、それは完璧に働いた。再度、感謝します! – XediDC

+0

問題ありません!ところで、I/OがNode内でブロックされていないことが重要です。あなたは同時に他の仕事をすることができます。しかし、同じ 'redis'クライアントを再利用してRedisを同時に呼び出しようとすると、あなたのループ_が干渉します。私は最近のプロジェクトでこのビット私と私は最初の1つのブロック中にコマンドを実行するために2番目の "非ブロッキング"クライアントが必要だと気づいたので言及します。 –

関連する問題