nodejsでredis PUBLISH / SUBSCRIBEを使用して、データ値が変更されたときにクライアントに通知する方法


99

NodeJSとRedisを使用して、イベント駆動型のパブリッシュ/サブスクライブアプリケーションを作成しています。Redisのデータ値が変更されたときにWebクライアントに通知する方法の例が必要です。

回答:


123

OLDは参照のみを使用します

依存関係

expresssocket.ionode_redisを使用しますが、最後にメディア火災からのサンプルコードを使用します。

node.js + npmをインストールします(非rootとして)

最初に(まだ行っていない場合)30秒でnode.js + npmをインストールする必要があります(rootとしてnpmを実行してはいけないため、正しい方法です):

echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
. ~/.bashrc
mkdir ~/local
mkdir ~/node-latest-install
cd ~/node-latest-install
curl http://nodejs.org/dist/node-latest.tar.gz | tar xz --strip-components=1
./configure --prefix=~/local
make install # ok, fine, this step probably takes more than 30 seconds...
curl http://npmjs.org/install.sh | sh

依存関係をインストールする

node + npmをインストールしたら、次を発行して依存関係をインストールする必要があります。

npm install express
npm install socket.io
npm install hiredis redis # hiredis to use c binding for redis => FAST :)

サンプルをダウンロード

完全なサンプルはmediafireからダウンロードできます。

パッケージを解凍

unzip pbsb.zip # can also do via graphical interface if you prefer.

中身は何ですか

./app.js

const PORT = 3000;
const HOST = 'localhost';

var express = require('express');

var app = module.exports = express.createServer();

app.use(express.staticProvider(__dirname + '/public'));

const redis = require('redis');
const client = redis.createClient();

const io = require('socket.io');

if (!module.parent) {
    app.listen(PORT, HOST);
    console.log("Express server listening on port %d", app.address().port)

    const socket  = io.listen(app);

    socket.on('connection', function(client) {
        const subscribe = redis.createClient();
        subscribe.subscribe('pubsub'); //    listen to messages from channel pubsub

        subscribe.on("message", function(channel, message) {
            client.send(message);
        });

        client.on('message', function(msg) {
        });

        client.on('disconnect', function() {
            subscribe.quit();
        });
    });
}

./public/index.html

<html>
<head>
    <title>PubSub</title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="/javascripts/jquery-1.4.3.min.js"></script>
</head>
<body>
    <div id="content"></div>
    <script>    
        $(document).ready(function() {
            var socket = new io.Socket('localhost', {port: 3000, rememberTransport: false/*, transports: ['xhr-polling']*/});
            var content = $('#content');

            socket.on('connect', function() {
            });

            socket.on('message', function(message){
                content.prepend(message + '<br />');
            }) ;

            socket.on('disconnect', function() {
                console.log('disconnected');
                content.html("<b>Disconnected!</b>");
            });

            socket.connect();
        });
    </script>
</body>
</html>

サーバーを起動

cd pbsb    
node app.js

ブラウザを起動

google chromeを開始するのが最適です(websocketがサポートされているためですが、必須ではありません)。http://localhost:3000サンプルを見るためにアクセスしてください(最初はPubSubタイトルとして何も表示されていません)。

しかし、publishチャンネルにpubsub行くとメッセージが表示されるはずです。以下は"Hello world!"ブラウザに公開しています。

./redis-cliから

publish pubsub "Hello world!"

なぜconst client = redis.createClient()app.jsのルートに必要なのですか?
Akasha 2012

constを使用する必要はまったくありません。varも使用できますが、constは新しいjavascriptエンジンでのみ使用できるため、代わりに使用する必要があるかもしれません。さらに、この行により、この例で使用するredisサーバーに確実に接続されます。
アルフレッド

5
サンプルは非常に古いため、最新のsocket.io/expressモジュールや、おそらくnode.jsでも最新ではありません。コードを更新してみます。このコードには、接続されている各ユーザーに対して別のredis接続を開くという大きな問題もあります。代わりにオンにする必要があります。最初に作業する必要がありますが、その後、コードを更新しようとします。
アルフレッド

1
とても良い。まだ改善の余地はあると思いますが、時間があるときにオンラインで公開します。しかし、今私は本当に一生懸命働いています:$。
アルフレッド

1
subscribe.onは、複数のsubscribes /を回避するためにsocket.on( 'connection')ブロックの外側にある必要があると思います/
zubinmehta

26

これは、依存関係のない単純化された例です。あなたはまだする必要がありますnpm install hiredis redis

ノードJavaScript:

var redis = require("redis"),
    client = redis.createClient();

client.subscribe("pubsub");
client.on("message", function(channel, message){
  console.log(channel + ": " + message);
});

...それをpubsub.jsファイルに入れて実行します node pubsub.js

redis-cli:

redis> publish pubsub "Hello Wonky!"
(integer) 1

表示する必要があります:pubsub: Hello Wonky!ノードを実行しているターミナルで!おめでとうございます!

追加4/23/2013:クライアントがpub / subチャネルをサブスクライブすると、サブスクライバーモードになり、サブスクライバーコマンドに限定されることにも注意したい。Redisクライアントの追加のインスタンスを作成する必要があるだけです。client1 = redis.createClient(), client2 = redis.createClient()そのため、1つはサブスクライバーモードで、もう1つは通常のDBコマンドを発行できます。


ここで、redisにデータを追加するときに、publish pubsubを実行して挿入の通知を取得する必要がありますか?
IshaS 2015

1
@IshaS必要な場合は、はい。複数のコマンドをアトミ​​ックに実行する必要がある場合は、トランザクションも調べる必要があります。redis.io
nak

@nakこれは1つのGOの魅力のように機能しました:)まだインストールされていない場合、一部のユーザーは「double-ended-queue」をインストールする必要がある場合があります。
Alex

1
ワイルドカードを使用したい場合は、例えば、サブスクライブすることを言及する価値もそれpubsub/*だけで追加p置き換える:例にsubscibeしてpsubscribemessageしてpmessage
Liosha Bakoushin

7

完全な Redis Pub / Subの例(Hapi.jsとSocket.ioを使用したリアルタイムチャット

私たちはRedis Publish / Subscribe( " Pub / Sub ")を理解しようとしていましたが、既存の例はすべて時代遅れであるか、単純すぎるか、テストがありませんでした。そこで、Hapi.js + Socket.io + Redis Pub / Subサンプルを使用し完全なリアルタイムチャットをエンドツーエンドテストで作成しました

https://github.com/dwyl/hapi-socketio- redis-chat-example

Pub / Subコンポーネントは、node.jsコードのほんの数行です:https : //github.com/dwyl/hapi-socketio-redis-chat-example/blob/master/lib/chat.js#L33-L40

ここに(コンテキストなしで)貼り付けるのではなく、をチェックアウト/試してみることをお勧めします。

私たちは、使用して構築されたHapi.jsが、chat.jsファイルがある・ド結合ハピからとすることができ、容易に使用する基本的な Node.jsのHTTPサーバーまたは表明(など)


あなたはエクスプレスでこの例を持っていますか?
Gixty、2015

@Gixty Hapi.jsを使用して例を記述したのは、他のすべての例ではExpress.jsを使用しているためです... chat.js initコードのリスナー)とまったく同じように機能します。ps:Hapi.jsを初めて使用する場合は、github.com / nelsonic
hapi

4

nodeisが終了しないように、redisエラーを処理します。これを行うには、次のように記述します。

subcribe.on("error", function(){
  //Deal with error
})

メッセージをパブリッシュするためにサブスクライブしているのと同じクライアントを使用しているため、例外が発生すると思います。メッセージを公開するための別のクライアントを作成します。これで問題が解決する可能性があります。



2

これをsocket.io 0.7で動作させたい場合、および外部Webサーバーを変更する必要がある場合(staticProvider-> staticの問題以外に):

a)localhostの代わりにドメイン名を提供します(つまり、var socket = io.connect( 'http://my.domain.com:3000');)をindex.htmlに指定します

b)app.jsのHOSTを変更します(つまり、const HOST = 'my.domain.com';)

c)app.jsの37行目にソケットを追加します(例: 'socket.sockets.on(' connection '、function(client){…')



0

@alexソリューションによると。@tylerの言及に従ってこのようなエラーが発生した場合:

node.js:134
        throw e; // process.nextTick error, or 'error'

event on first tick ^ Error: Redis connection to 127.0.0.1:6379 failed - ECONNREFUSED, Connection refused at Socket.

次に、Redisを最初にインストールする必要があります。これをチェックしてください:

http://redis.io/download

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.