Skip to content

Commit

Permalink
Integrate Redis and NGINX proxy/load balancer for backend services
Browse files Browse the repository at this point in the history
  • Loading branch information
williamtnguyen committed May 8, 2021
1 parent 88e8390 commit 8a1f479
Show file tree
Hide file tree
Showing 17 changed files with 483 additions and 165 deletions.
6 changes: 3 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
"@types/jest": "^24.9.1",
"@types/node": "^12.12.67",
"@types/react": "^16.9.53",
"mediasoup": "^3.7.0",
"mediasoup-client": "^3.6.29",
"@types/react-beautiful-dnd": "^13.0.0",
"antd": "^4.14.1",
"mediasoup": "^3.7.0",
"mediasoup-client": "^3.6.29",
"node-sass": "^4.14.1",
"react": "^16.13.1",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.4",
"react-youtube": "^7.13.0",
"socket.io-client": "^2.3.1",
"socket.io-client": "^4.0.1",
"typescript": "^3.7.5"
},
"scripts": {
Expand Down
4 changes: 3 additions & 1 deletion client/src/utils/rtc-socket-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const openRtcSocket = (
redisClientId: string
): Promise<SocketIOClient.Socket> => {
return new Promise((resolve) => {
const socket = io(rtcServerDomain);
const socket = io(rtcServerDomain, {
path: '/rtcService',
});

socket.on('connect', () => {
const clientData = {
Expand Down
4 changes: 3 additions & 1 deletion client/src/utils/session-socket-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export const openSessionSocket = (
roomId?: string
): Promise<SocketIOClient.Socket> => {
return new Promise((resolve) => {
const socket = io(sessionServerDomain);
const socket = io(sessionServerDomain, {
path: '/sessionService',
});

socket.on('connect', () => {
const clientData = {
Expand Down
59 changes: 59 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Spins up mock production environment
version: '3'
services:
# Reverse proxy/load balancer
nginx:
build: ./nginx
depends_on:
- rtcServer
- sessionServer
ports:
- '5000:80'

# mediasoup voice server
rtcServer:
build:
context: ./rtc-server
dockerfile: Dockerfile
image: insync-rtc-service
volumes:
- /rtc-server/node_modules
expose:
- '4000'

# socketio session server
sessionServer:
build:
context: ./server
dockerfile: Dockerfile
image: insync-session-service
volumes:
- /server/node_modules
expose:
- '5000'
depends_on:
- redisSocketIoAdapter
- redisRoomState
- redisClientRoomId
- redisWaitingRoomId

# spin up 4 redis containers, 1 for socket.io adapter, 3 for holding room state
redisSocketIoAdapter:
image: redis:alpine
expose:
- '6379'
redisRoomState:
image: redis:alpine
command: --port 6380
expose:
- '6380'
redisClientRoomId:
image: redis:alpine
command: --port 6381
expose:
- '6381'
redisWaitingRoomId:
image: redis:alpine
command: --port 6382
expose:
- '6382'
2 changes: 2 additions & 0 deletions nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
44 changes: 44 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
worker_processes 4;

events {
worker_connections 1024;
}

http {
server {
listen 80;

location /rtcService/ {
# enable WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://rtc_server;
}

location /sessionService/ {
# enable WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://socket_nodes;
}
}

upstream rtc_server {
ip_hash;
server rtcServer:4000;
}

upstream socket_nodes {
ip_hash;
server sessionServer:5000;
# TODO: add more physical nodes
}
}
23 changes: 23 additions & 0 deletions rtc-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Base alpine image to install npm packages and compile ts -> js
FROM node:14-alpine AS build
COPY . .
RUN apk update \
&& apk add --no-cache --virtual .gyp \
python \
make \
g++ \
linux-headers \
&& npm install \
&& npm install mediasoup \
&& npm run build \
&& apk del .gyp

# Main application image
FROM node:14-alpine
WORKDIR /server
COPY --from=build ./node_modules ./node_modules
COPY --from=build ./build ./build
RUN npm install pm2 -g
ENV NODE_ENV=production
EXPOSE 4000
CMD ["pm2-runtime", "./build/server.js"]
2 changes: 1 addition & 1 deletion rtc-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dependencies": {
"express": "^4.17.1",
"mediasoup": "^3.7.4",
"socket.io": "^2.4.1"
"socket.io": "^4.0.1"
},
"devDependencies": {
"@types/express": "^4.17.11",
Expand Down
15 changes: 11 additions & 4 deletions rtc-server/server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import express, { Application } from 'express';
import http, { Server } from 'http';
import socketIo, { Server as WebSocketServer } from 'socket.io';
import http, { Server as HttpServer } from 'http';
import { Server as WebSocketServer } from 'socket.io';
import attachSocketEvents from './utils/attach-socket-events';

const app: Application = express();
const server: Server = http.createServer(app);
const io: WebSocketServer = socketIo(server, { serveClient: false });
const server: HttpServer = http.createServer(app);
const io: WebSocketServer = new WebSocketServer(server, {
serveClient: false,
path: '/rtcService',
cors: {
methods: ['GET', 'PATCH', 'POST', 'PUT'],
origin: true,
},
});
attachSocketEvents(io);

const PORT: string | number = process.env.PORT || 4000;
Expand Down
9 changes: 9 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:14-alpine
WORKDIR /server
COPY . .
RUN npm install \
&& npm install -g pm2 \
&& npm run build
ENV NODE_ENV=production
EXPOSE 5000
CMD ["pm2-runtime", "./build/server.js"];
22 changes: 22 additions & 0 deletions server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Spins up all redis containers for development purposes
version: '3'
services:
redisSocketIoAdapter:
image: redis:alpine
ports:
- '6379:6379'
redisRoomState:
image: redis:alpine
command: --port 6380
ports:
- '6380:6380'
redisClientRoomId:
image: redis:alpine
command: --port 6381
ports:
- '6381:6381'
redisWaitingRoomId:
image: redis:alpine
command: --port 6382
ports:
- '6382:6382'
5 changes: 4 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
"dependencies": {
"express": "^4.17.1",
"linked-list": "^2.1.0",
"socket.io": "^2.4.1"
"redis": "^3.1.2",
"socket.io": "^4.0.1",
"socket.io-redis": "^6.1.0"
},
"devDependencies": {
"@types/express": "^4.17.8",
"@types/node": "^14.11.8",
"@types/redis": "^2.8.28",
"@types/socket.io": "^2.1.11",
"nodemon": "^2.0.4",
"prettier": "^2.1.2",
Expand Down
23 changes: 19 additions & 4 deletions server/server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import express, { Application } from 'express';
import http, { Server } from 'http';
import socketIo, { Server as WebSocketServer } from 'socket.io';
import http, { Server as HttpServer } from 'http';
import { Server as WebSocketServer } from 'socket.io';
import attachSocketEvents from './utils/attach-socket-events';
import { createAdapter } from 'socket.io-redis';
import redisClients from './utils/redis-clients';

const app: Application = express();
const server: Server = http.createServer(app);
const io: WebSocketServer = socketIo(server, { serveClient: false });
const server: HttpServer = http.createServer(app);
const io: WebSocketServer = new WebSocketServer(server, {
serveClient: false,
path: '/sessionService',
cors: {
methods: ['GET', 'PATCH', 'POST', 'PUT'],
origin: true,
},
});
io.adapter(
createAdapter({
pubClient: redisClients.adapterPubClient,
subClient: redisClients.adapterSubClient,
})
);
attachSocketEvents(io);

const PORT: string | number = process.env.PORT || 5000;
Expand Down
14 changes: 10 additions & 4 deletions server/utils/Playlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,21 @@ interface PlaylistMap {

/**
* Playlist class implemented with Doubly-Linked-List and HashMap
* for O(1) node insertion/deletion/mutation
*/
export class Playlist {
private list: typeof LinkedList;
private map: PlaylistMap; // maps array position to node pointer

constructor() {
this.list = new LinkedList();
// costly initialization but the most seamless refactor
constructor(playlistSnapshot: string[]) {
this.map = {};
this.list = new LinkedList();

playlistSnapshot.forEach((youtubeId: string, index: number) => {
const node = new VideoNode(youtubeId);
this.list.append(node);
this.map[index] = node;
});
}

getYoutubeIDAtIndex(videoIndex: number): string {
Expand Down Expand Up @@ -82,4 +88,4 @@ export class Playlist {
}
}

export default new Playlist();
export default Playlist;
Loading

0 comments on commit 8a1f479

Please sign in to comment.