node + Redis でpub/subを楽しむとしてRedisがフェイルオーバーしたらどうなっねんと
メモ書き程度の能力。
Redis のインストール
node で Redis の Subscribe機能を使う
Redis の Pub/Sub を使って Node.js + WebSocket のスケールアウトを実現する方法 | dakatsuka's blog
Redis で master/slave 設定
Redis Sentinel で自動フェイルオーバー
Redisがフェイルオーバーすると
node から Redis のSubscribe をしている最中にフェイルオーバー起こったら、 Redis との接続切れるよな……再接続したとして、正常に購読しなおせるのかな……と 疑問に思ったので試す。
Subscribeするサンプルコード
var sys = require('sys'); var redis = require('redis'); var subscriber = redis.createClient(6379, 'localhost'); subscriber.subscribe('hoge'); subscriber.on("message", function(channel, message) { sys.puts(channel + " :" + message); }); subscriber.on('error', function(err) { console.log('redis_err ' + String(err)); });
別端末からPublishすると当然 Subscribeできてる。
% redis-cli 127.0.0.1:6379> 127.0.0.1:6379> PUBLISH hoge "Hello World!" (integer) 1
この状態でフェイルオーバーしたと仮定して、redis-sever を再起動させてみる。
再度上記のコマンドで Publish してみると、フェイルオーバー後もnodeが Redisに再接続し、再購読しなおしてる事が確認できる。
めでたしめでたし。
なんで
node-redis モジュールが勝手に Reconnectしてくれてる。具体的に言うと 下記のようにerrorイベントさえハンドリングしとけば Redisとの接続が切れても再接続しなおしてくれる。
subscriber.on('error', function(err) { console.log('redis_err ' + String(err)); });
逆に言うとハンドリングしなければRedisとの接続が切れるとnode側も巻き込まれて落ちる。
その他ハマったこと
var sys = require('sys'); var redis = require('redis'); var subscriber = redis.createClient(6379, 'localhost'); subscriber.on("connect", function(){ subscriber.subscribe('hoge'); subscriber.on("message", function(channel, message) { sys.puts(channel + " :" + message); }); }); subscriber.on('error', function(err) { console.log('redis_err ' + String(err)); });
当初は上記のようにconnectイベントにハンドリングして購読してた。 connectイベントは最初の接続時はもちろんのこと、再接続時も発行されるので うまく購読できるように見えて、再接続時はうまいこと購読できなかった。