Skip to content

Commit

Permalink
[docs] Add nginx cluster example (socketio#2817)
Browse files Browse the repository at this point in the history
  • Loading branch information
darrachequesne committed Jan 16, 2017
1 parent 4c0369e commit c27301b
Show file tree
Hide file tree
Showing 10 changed files with 697 additions and 0 deletions.
31 changes: 31 additions & 0 deletions examples/cluster-nginx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

# Socket.IO Chat with nginx & redis

A simple chat demo for socket.io

## How to use

Install [Docker Compose](https://docs.docker.com/compose/install/), then:

```
$ docker-compose up -d
```

And then point your browser to `http://localhost:3000`.

This will start four Socket.IO nodes, behind a nginx proxy which will loadbalance the requests (using the IP of the client, see [ip_hash](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash)).

Each node connects to the redis backend, which will enable to broadcast to every client, no matter which node it is currently connected to.

```
# you can kill a given node, the client should reconnect to another node
$ docker-compose stop server-george
```

## Features

- 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.
51 changes: 51 additions & 0 deletions examples/cluster-nginx/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

nginx:
build: ./nginx
links:
- server-john
- server-paul
- server-george
- server-ringo
ports:
- "3000:80"

server-john:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=John

server-paul:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=Paul

server-george:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=George

server-ringo:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=Ringo

redis:
image: redis:alpine
expose:
- "6379"
3 changes: 3 additions & 0 deletions examples/cluster-nginx/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
35 changes: 35 additions & 0 deletions examples/cluster-nginx/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Reference: https://www.nginx.com/resources/wiki/start/topics/examples/full/

worker_processes 4;

events {
worker_connections 1024;
}

http {
server {
listen 80;

location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;

proxy_pass http://nodes;

# enable WebSockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

upstream nodes {
# enable sticky session
ip_hash;

server server-john:3000;
server server-paul:3000;
server server-george:3000;
server server-ringo:3000;
}
}
15 changes: 15 additions & 0 deletions examples/cluster-nginx/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM mhart/alpine-node:6

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 3000
CMD [ "npm", "start" ]
82 changes: 82 additions & 0 deletions examples/cluster-nginx/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var redis = require('socket.io-redis');
var port = process.env.PORT || 3000;
var serverName = process.env.NAME || 'Unknown';

io.adapter(redis({ host: 'redis', port: 6379 }));

server.listen(port, function () {
console.log('Server listening at port %d', port);
console.log('Hello, I\'m %s, how can I help?', serverName);
});

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

// Chatroom

var numUsers = 0;

io.on('connection', function (socket) {
socket.emit('my-name-is', serverName);

var addedUser = false;

// when the client emits 'new message', this listens and executes
socket.on('new message', function (data) {
// we tell the client to execute 'new message'
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) {
if (addedUser) return;

// we store the username in the socket session for this client
socket.username = username;
++numUsers;
addedUser = true;
socket.emit('login', {
numUsers: numUsers
});
// echo globally (all clients) that a person has connected
socket.broadcast.emit('user joined', {
username: socket.username,
numUsers: numUsers
});
});

// 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 () {
if (addedUser) {
--numUsers;

// echo globally that this client has left
socket.broadcast.emit('user left', {
username: socket.username,
numUsers: numUsers
});
}
});
});
17 changes: 17 additions & 0 deletions examples/cluster-nginx/server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"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": "4.13.4",
"socket.io": "^1.7.2",
"socket.io-redis": "^3.0.0"
},
"scripts": {
"start": "node index.js"
}
}
28 changes: 28 additions & 0 deletions examples/cluster-nginx/server/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

0 comments on commit c27301b

Please sign in to comment.