How to use redis PUBLISH/SUBSCRIBE with nodejs to notify clients when data values change?
OLD only use a reference
Dependencies
uses express, socket.io, node_redis and last but not least the sample code from media fire.
Install node.js+npm(as non root)
First you should(if you have not done this yet) install node.js+npm in 30 seconds (the right way because you should NOT run npm as root):
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
Install dependencies
After you installed node+npm you should install dependencies by issuing:
npm install express
npm install socket.io
npm install hiredis redis # hiredis to use c binding for redis => FAST :)
Download sample
You can download complete sample from mediafire.
Unzip package
unzip pbsb.zip # can also do via graphical interface if you prefer.
What's inside zip
./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>
Start server
cd pbsb
node app.js
Start browser
Best if you start google chrome(because of websockets support, but not necessary). Visit http://localhost:3000
to see sample(in the beginning you don't see anything but PubSub
as title).
But on publish
to channel pubsub
you should see a message. Below we publish "Hello world!"
to the browser.
From ./redis-cli
publish pubsub "Hello world!"
here's a simplified example without as many dependencies.
You do still need to npm install hiredis redis
The node JavaScript:
var redis = require("redis"),
client = redis.createClient();
client.subscribe("pubsub");
client.on("message", function(channel, message){
console.log(channel + ": " + message);
});
...put that in a pubsub.js file and run node pubsub.js
in redis-cli:
redis> publish pubsub "Hello Wonky!"
(integer) 1
which should display: pubsub: Hello Wonky!
in the terminal running node!
Congrats!
Additional 4/23/2013: I also want to make note that when a client subscribes to a pub/sub channel it goes into subscriber mode and is limited to subscriber commands. You'll just need to create additional instances of redis clients. client1 = redis.createClient(), client2 = redis.createClient()
so one can be in subscriber mode and the other can issue regular DB commands.
Complete Redis Pub/Sub Example (Real-time Chat using Hapi.js & Socket.io)
We were trying to understand Redis Publish/Subscribe ("Pub/Sub") and all the existing examples were either outdated, too simple or had no tests. So we wrote a Complete Real-time Chat using Hapi.js + Socket.io + Redis Pub/Sub Example with End-to-End Tests!
https://github.com/dwyl/hapi-socketio-redis-chat-example
The Pub/Sub component is only a few lines of node.js code: https://github.com/dwyl/hapi-socketio-redis-chat-example/blob/master/lib/chat.js#L33-L40
Rather than pasting it here (without any context) we encourage you to checkout/try the example.
We built it using Hapi.js but the chat.js
file is de-coupled from Hapi and can easily be used with a basic node.js http server or express (etc.)
Handle redis errors to stop nodejs from exiting. You can do this by writing;
subcribe.on("error", function(){
//Deal with error
})
I think you get the exception because you are using the same client which is subscribed to publish messages. Create a separate client for publishing messages and that could solve your problem.
Check out acani-node on GitHub, especially the file acani-node-server.js. If these links are broken, look for acani-chat-server among acani's GitHub public repositories.