Skip to content
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

Integrate Redis and NGINX proxy/load balancer for backend services #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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