Skip to content

Chat example using Cluster + Redis Adapter #1815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions examples/chat-cluster/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

# Socket.IO Chat

A simple chat demo for socket.io

## How to use


### Starting Redis
This example uses Redis for communication between sockets that may be connected on different slave processes of the Node application.

To install `redis-server` follow http://redis.io/topics/quickstart

Run redis with the default configuration. It will run on localhost port 6379. This runs Redis in the foreground so keep this Terminal window open.

```
$ redis-server
```

### Running the example application

```
$ cd socket.io
$ npm install
$ cd examples/chat-cluster
$ npm install
$ node .
```

And point your browser to `http://localhost:3000`. Optionally, specify
a port by supplying the `PORT` env variable.

## Cluster Chat Features

- Forks the node process multiple times and routes requests to one of the slave processes of Node.


## Basic Chat Features (See other example)

- Multiple users can join a chat room by each entering a unique username
on website load.
- Users can type chat messages to the chat room.
- A notification is sent to all users when a user joins or leaves
the chatroom.
152 changes: 152 additions & 0 deletions examples/chat-cluster/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Setup basic express server
var express = require('express');
var app = express();
// var server = require('http').createServer(app);
var http = require('http');
var port = process.env.PORT || 3000

// Required for cluster
var redisAdapter = require('socket.io-redis');
var sticky = require('sticky-session');
var redis = require('redis');
var cluster = require('cluster');

// number of slaves
var workers = process.env.WORKERS || 5; // use 5 slaves if no number of works is specified


///////////////////////////////////
// Server
//
// Configure sticky sessions to ensure requests go to the same
// child in the cluster.
// See : https://github.com/indutny/sticky-session
// NOTE: Sticky sessions are based on a hash of the IP address.
// This means multiple web browsers or tabs on the same machine
// will always hit the same slave.
//
///////////////////////////////////

sticky(workers, function() {

// This code will be executed only in slave workers
var server = http.createServer(app);

var io = require('../..')(server);
//var io = require('socket.io')(server);

// configure socket.io to use redis adapter
addRedisAdapter(io);

// configure socket.io to respond to certain events
addIOEventHandlers(io);

return server;

}).listen(port, function() {

// this code is executed in both slaves and master
console.log('server started on port '+port+'. process id = '+process.pid);

});


///////////////////////////////////
// Routing
///////////////////////////////////

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


///////////////////////////////////
// Redis Adapter
///////////////////////////////////

function addRedisAdapter(io) {
var redisUrl = process.env.REDISTOGO_URL || 'redis://127.0.0.1:6379';
var redisOptions = require('parse-redis-url')(redis).parse(redisUrl);
var pub = redis.createClient(redisOptions.port, redisOptions.host, {
detect_buffers: true,
auth_pass: redisOptions.password
});
var sub = redis.createClient(redisOptions.port, redisOptions.host, {
detect_buffers: true,
auth_pass: redisOptions.password
});

io.adapter(redisAdapter({
pubClient: pub,
subClient: sub
}));
console.log('Redis adapter started with url: ' + redisUrl);
};

///////////////////////////////////
// Chatroom Handlers
///////////////////////////////////

// usernames which are currently connected to the chat
// var usernames = {};
// var numUsers = 0;

function addIOEventHandlers(io) {

io.on('connection', function (socket) {

// var addedUser = false;
console.log('Connection made. socket.id='+socket.id+' . pid = '+process.pid);

// when the client emits 'new message', this listens and executes
socket.on('new message', function (data) {
// we tell the client to execute 'new message'

console.log('emitting message: "'+data+'". socket.id='+socket.id+' . pid = '+process.pid);
socket.broadcast.emit('new message', {
username: socket.username,
message: data
});
});

// when the client emits 'add user', this listens and executes
socket.on('add user', function (username) {
// we store the username in the socket session for this client
socket.username = username;
// add the client's username to the global list
// usernames[username] = username;
// ++numUsers;
// addedUser = true;
socket.emit('login', { // todo
numUsers: 420
});
// echo globally (all clients) that a person has connected
socket.broadcast.emit('user joined', { // todo
username: socket.username,
numUsers: 421
});
});

// when the client emits 'typing', we broadcast it to others
socket.on('typing', function () {
socket.broadcast.emit('typing', {
username: socket.username
});
});

// when the client emits 'stop typing', we broadcast it to others
socket.on('stop typing', function () {
socket.broadcast.emit('stop typing', {
username: socket.username
});
});

// when the user disconnects.. perform this
socket.on('disconnect', function () {
socket.broadcast.emit('user left', { // todo
username: socket.username,
numUsers: 422
});
});

});

};
16 changes: 16 additions & 0 deletions examples/chat-cluster/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "socket.io-chat",
"version": "0.0.0",
"description": "A simple chat client using socket.io",
"main": "index.js",
"author": "Grant Timmerman",
"private": true,
"license": "BSD",
"dependencies": {
"express": "3.4.8",
"parse-redis-url": "0.0.1",
"redis": "^0.12.1",
"socket.io-redis": "^0.1.3",
"sticky-session": "^0.1.0"
}
}
28 changes: 28 additions & 0 deletions examples/chat-cluster/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO Chat Example</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<ul class="pages">
<li class="chat page">
<div class="chatArea">
<ul class="messages"></ul>
</div>
<input class="inputMessage" placeholder="Type here..."/>
</li>
<li class="login page">
<div class="form">
<h3 class="title">What's your nickname?</h3>
<input class="usernameInput" type="text" maxlength="14" />
</div>
</li>
</ul>

<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/main.js"></script>
</body>
</html>
Loading