Performance improvements

- added redis to socket.io 
- added node cluster and enabled running on all cpu cores
pull/2/head
Trivernis 5 years ago
parent 5454bd1d86
commit 8de1de44f1

56
package-lock.json generated

@ -278,11 +278,18 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.2.tgz",
"integrity": "sha512-Ind+4qMNfQ62llyB4IMs1D8znMEBsMKohZBPqfBUIXqLQ9bdtWIbNTBWwtdcBWJKnokMZGcmWOOKslatni5vtA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/socket.io-redis": {
"version": "1.0.25",
"resolved": "https://registry.npmjs.org/@types/socket.io-redis/-/socket.io-redis-1.0.25.tgz",
"integrity": "sha512-a1b6eW/8CWsIVOhkwkGCNLgXy8G+Vo1rrpRjs9l+1/V/yZV3p0U6V002ZFJ26iNclloCcKJMklJGVkqPRBvDtA==",
"requires": {
"@types/socket.io": "*"
}
},
"@types/validator": {
"version": "10.11.3",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.3.tgz",
@ -1844,6 +1851,11 @@
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz",
"integrity": "sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw=="
},
"double-ended-queue": {
"version": "2.1.0-0",
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
"integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw="
},
"duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@ -4984,6 +4996,11 @@
"remove-trailing-separator": "^1.0.1"
}
},
"notepack.io": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-2.1.3.tgz",
"integrity": "sha512-AgSt+cP5XMooho1Ppn8NB3FFaVWefV+qZoZncYTUSch2GAEwlYLcIIbT5YVkMlFeNHnfwOvc4HDlbvrB5BRxXA=="
},
"now-and-later": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz",
@ -5849,6 +5866,26 @@
"strip-indent": "^1.0.1"
}
},
"redis": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz",
"integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==",
"requires": {
"double-ended-queue": "^2.1.0-0",
"redis-commands": "^1.2.0",
"redis-parser": "^2.6.0"
}
},
"redis-commands": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz",
"integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg=="
},
"redis-parser": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz",
"integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs="
},
"reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
@ -6556,6 +6593,18 @@
}
}
},
"socket.io-redis": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/socket.io-redis/-/socket.io-redis-5.2.0.tgz",
"integrity": "sha1-j+KtlEX8UIhvtwq8dZ1nQD1Ymd8=",
"requires": {
"debug": "~2.6.8",
"notepack.io": "~2.1.2",
"redis": "~2.8.0",
"socket.io-adapter": "~1.1.0",
"uid2": "0.0.3"
}
},
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
@ -7368,6 +7417,11 @@
"random-bytes": "~1.0.0"
}
},
"uid2": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
"integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I="
},
"unc-path-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",

@ -51,6 +51,7 @@
"typescript": "^3.5.3"
},
"dependencies": {
"@types/socket.io-redis": "^1.0.25",
"compression": "^1.7.4",
"connect-session-sequelize": "^6.0.0",
"cookie-parser": "^1.4.4",
@ -72,6 +73,7 @@
"sequelize": "^5.19.6",
"sequelize-typescript": "^1.0.0",
"socket.io": "^2.2.0",
"socket.io-redis": "^5.2.0",
"sqlite3": "^4.1.0",
"winston": "^3.2.1",
"winston-daily-rotate-file": "^4.2.1"

@ -14,6 +14,7 @@ import * as httpStatus from "http-status";
import * as path from "path";
import {Sequelize} from "sequelize-typescript";
import * as socketIo from "socket.io";
import * as socketIoRedis from "socket.io-redis";
import {resolver} from "./graphql/resolvers";
import dataaccess from "./lib/dataaccess";
import globals from "./lib/globals";
@ -26,9 +27,11 @@ class App {
public app: express.Application;
public io: socketIo.Server;
public server: http.Server;
public readonly id?: number;
public readonly sequelize: Sequelize;
constructor() {
constructor(id?: number) {
this.id = id;
this.app = express();
this.server = new http.Server(this.app);
this.io = socketIo(this.server);
@ -56,7 +59,7 @@ class App {
logger.info(`Sequelize Table force: ${force}`);
await this.sequelize.sync({force, logging: (msg) => logger.silly(msg)});
await routes.ioListeners(this.io);
this.io.adapter(socketIoRedis());
this.io.use(sharedsession(appSession, {autoSave: true}));
this.app.set("views", path.join(__dirname, "views"));
@ -69,6 +72,7 @@ class App {
this.app.use(express.static(path.join(__dirname, "public")));
this.app.use(cookieParser());
this.app.use(appSession);
// enable cross origin requests if enabled in the config
if (globals.config.server.cors) {
this.app.use(cors());
}
@ -77,6 +81,7 @@ class App {
next();
});
this.app.use(routes.router);
// listen for graphql requrest
this.app.use("/graphql", graphqlHTTP((request, response) => {
return {
// @ts-ignore all
@ -86,14 +91,28 @@ class App {
schema: buildSchema(importSchema(path.join(__dirname, "./graphql/schema.graphql"))),
};
}));
// allow access to cluster information
this.app.use("/cluster-info", (req: Request, res: Response) => {
res.json({
id: this.id,
});
});
// redirect all request to the angular file
this.app.use((req: any, res: Response) => {
if (globals.config.frontend.angularIndex) {
res.sendFile(path.join(__dirname, globals.config.frontend.angularIndex));
const angularIndex = path.join(__dirname, globals.config.frontend.angularIndex);
if (fsx.existsSync(path.join(angularIndex))) {
res.sendFile(angularIndex);
} else {
res.status(httpStatus.NOT_FOUND);
res.render("errors/404.pug", {url: req.url});
}
} else {
res.status(httpStatus.NOT_FOUND);
res.render("errors/404.pug", {url: req.url});
}
});
// show an error page for internal errors
this.app.use((err, req: Request, res: Response) => {
res.status(httpStatus.INTERNAL_SERVER_ERROR);
res.render("errors/500.pug");

@ -1,11 +1,26 @@
// tslint:disable:no-console
import * as cluster from "cluster";
import App from "./app";
const numCPUs = require("os").cpus().length;
/**
* async main function wrapper.
*/
(async () => {
const app = new App();
await app.init();
app.start();
})();
if (cluster.isMaster) {
console.log(`[CLUSTER] Master ${process.pid} is running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`[CLUSTER] Worker ${worker.process.pid} died!`);
});
} else {
/**
* async main function wrapper.
*/
(async () => {
const app = new App(process.pid);
await app.init();
app.start();
})();
console.log(`[CLUSTER] Worker ${process.pid} started`);
}

Loading…
Cancel
Save