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", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.2.tgz",
"integrity": "sha512-Ind+4qMNfQ62llyB4IMs1D8znMEBsMKohZBPqfBUIXqLQ9bdtWIbNTBWwtdcBWJKnokMZGcmWOOKslatni5vtA==", "integrity": "sha512-Ind+4qMNfQ62llyB4IMs1D8znMEBsMKohZBPqfBUIXqLQ9bdtWIbNTBWwtdcBWJKnokMZGcmWOOKslatni5vtA==",
"dev": true,
"requires": { "requires": {
"@types/node": "*" "@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": { "@types/validator": {
"version": "10.11.3", "version": "10.11.3",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.3.tgz", "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", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz",
"integrity": "sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw==" "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": { "duplexify": {
"version": "3.7.1", "version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@ -4984,6 +4996,11 @@
"remove-trailing-separator": "^1.0.1" "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": { "now-and-later": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz",
@ -5849,6 +5866,26 @@
"strip-indent": "^1.0.1" "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": { "reflect-metadata": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "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": { "source-map": {
"version": "0.7.3", "version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
@ -7368,6 +7417,11 @@
"random-bytes": "~1.0.0" "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": { "unc-path-regex": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",

@ -51,6 +51,7 @@
"typescript": "^3.5.3" "typescript": "^3.5.3"
}, },
"dependencies": { "dependencies": {
"@types/socket.io-redis": "^1.0.25",
"compression": "^1.7.4", "compression": "^1.7.4",
"connect-session-sequelize": "^6.0.0", "connect-session-sequelize": "^6.0.0",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.4",
@ -72,6 +73,7 @@
"sequelize": "^5.19.6", "sequelize": "^5.19.6",
"sequelize-typescript": "^1.0.0", "sequelize-typescript": "^1.0.0",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
"socket.io-redis": "^5.2.0",
"sqlite3": "^4.1.0", "sqlite3": "^4.1.0",
"winston": "^3.2.1", "winston": "^3.2.1",
"winston-daily-rotate-file": "^4.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 * as path from "path";
import {Sequelize} from "sequelize-typescript"; import {Sequelize} from "sequelize-typescript";
import * as socketIo from "socket.io"; import * as socketIo from "socket.io";
import * as socketIoRedis from "socket.io-redis";
import {resolver} from "./graphql/resolvers"; import {resolver} from "./graphql/resolvers";
import dataaccess from "./lib/dataaccess"; import dataaccess from "./lib/dataaccess";
import globals from "./lib/globals"; import globals from "./lib/globals";
@ -26,9 +27,11 @@ class App {
public app: express.Application; public app: express.Application;
public io: socketIo.Server; public io: socketIo.Server;
public server: http.Server; public server: http.Server;
public readonly id?: number;
public readonly sequelize: Sequelize; public readonly sequelize: Sequelize;
constructor() { constructor(id?: number) {
this.id = id;
this.app = express(); this.app = express();
this.server = new http.Server(this.app); this.server = new http.Server(this.app);
this.io = socketIo(this.server); this.io = socketIo(this.server);
@ -56,7 +59,7 @@ class App {
logger.info(`Sequelize Table force: ${force}`); logger.info(`Sequelize Table force: ${force}`);
await this.sequelize.sync({force, logging: (msg) => logger.silly(msg)}); await this.sequelize.sync({force, logging: (msg) => logger.silly(msg)});
await routes.ioListeners(this.io); await routes.ioListeners(this.io);
this.io.adapter(socketIoRedis());
this.io.use(sharedsession(appSession, {autoSave: true})); this.io.use(sharedsession(appSession, {autoSave: true}));
this.app.set("views", path.join(__dirname, "views")); 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(express.static(path.join(__dirname, "public")));
this.app.use(cookieParser()); this.app.use(cookieParser());
this.app.use(appSession); this.app.use(appSession);
// enable cross origin requests if enabled in the config
if (globals.config.server.cors) { if (globals.config.server.cors) {
this.app.use(cors()); this.app.use(cors());
} }
@ -77,6 +81,7 @@ class App {
next(); next();
}); });
this.app.use(routes.router); this.app.use(routes.router);
// listen for graphql requrest
this.app.use("/graphql", graphqlHTTP((request, response) => { this.app.use("/graphql", graphqlHTTP((request, response) => {
return { return {
// @ts-ignore all // @ts-ignore all
@ -86,14 +91,28 @@ class App {
schema: buildSchema(importSchema(path.join(__dirname, "./graphql/schema.graphql"))), 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) => { this.app.use((req: any, res: Response) => {
if (globals.config.frontend.angularIndex) { 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 { } else {
res.status(httpStatus.NOT_FOUND); res.status(httpStatus.NOT_FOUND);
res.render("errors/404.pug", {url: req.url}); res.render("errors/404.pug", {url: req.url});
} }
}); });
// show an error page for internal errors
this.app.use((err, req: Request, res: Response) => { this.app.use((err, req: Request, res: Response) => {
res.status(httpStatus.INTERNAL_SERVER_ERROR); res.status(httpStatus.INTERNAL_SERVER_ERROR);
res.render("errors/500.pug"); res.render("errors/500.pug");

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