Add ability to run server cluster
This commit is contained in:
parent
0633734156
commit
17adb818be
@ -8,6 +8,8 @@ export interface Bootstrap {
|
|||||||
readonly database: TypeORMDatabase
|
readonly database: TypeORMDatabase
|
||||||
getConfig(): Config
|
getConfig(): Config
|
||||||
listen(port?: number | string, hostname?: string): Promise<void>
|
listen(port?: number | string, hostname?: string): Promise<void>
|
||||||
|
startCluster(
|
||||||
|
workers: number, port?: number | string, hostname?: string): Promise<void>
|
||||||
getAddress(): AddressInfo | string
|
getAddress(): AddressInfo | string
|
||||||
close(): Promise<void>
|
close(): Promise<void>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
import { TypeORMDatabase, TypeORMLogger } from '@rondo.dev/db-typeorm'
|
||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
import { createNamespace, Namespace } from 'cls-hooked'
|
import { createNamespace, Namespace } from 'cls-hooked'
|
||||||
|
import cluster from 'cluster'
|
||||||
import { Server } from 'http'
|
import { Server } from 'http'
|
||||||
import { AddressInfo } from 'net'
|
import { AddressInfo } from 'net'
|
||||||
import { loggerFactory } from '../logger'
|
import { loggerFactory } from '../logger'
|
||||||
@ -8,7 +10,7 @@ import { Bootstrap } from './Bootstrap'
|
|||||||
import { Config } from './Config'
|
import { Config } from './Config'
|
||||||
import { ServerConfigurator } from './configureServer'
|
import { ServerConfigurator } from './configureServer'
|
||||||
import { createServer } from './createServer'
|
import { createServer } from './createServer'
|
||||||
import { TypeORMDatabase, TypeORMLogger } from '@rondo.dev/db-typeorm'
|
|
||||||
|
|
||||||
export interface ServerBootstrapParams {
|
export interface ServerBootstrapParams {
|
||||||
readonly config: Config
|
readonly config: Config
|
||||||
@ -79,7 +81,7 @@ export class ServerBootstrap implements Bootstrap {
|
|||||||
|
|
||||||
async listen(
|
async listen(
|
||||||
port: number | string | undefined = process.env.PORT || 3000,
|
port: number | string | undefined = process.env.PORT || 3000,
|
||||||
hostname: string | undefined= process.env.BIND_HOST,
|
hostname: string | undefined = process.env.BIND_HOST,
|
||||||
) {
|
) {
|
||||||
const apiLogger = loggerFactory.getLogger('api')
|
const apiLogger = loggerFactory.getLogger('api')
|
||||||
try {
|
try {
|
||||||
@ -91,6 +93,36 @@ export class ServerBootstrap implements Bootstrap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async startCluster(
|
||||||
|
workers: number,
|
||||||
|
port?: number | string,
|
||||||
|
hostname?: string,
|
||||||
|
) {
|
||||||
|
const apiLogger = loggerFactory.getLogger('api')
|
||||||
|
|
||||||
|
if (cluster.isMaster) {
|
||||||
|
apiLogger.info('Started master process %d, starting %d workers...',
|
||||||
|
process.pid, workers)
|
||||||
|
|
||||||
|
// Fork workers.
|
||||||
|
for (let i = 0; i < workers; i++) {
|
||||||
|
cluster.fork({
|
||||||
|
WORKER_ID: i + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster.on('exit', (worker, code, signal) => {
|
||||||
|
console.log(`worker ${worker.process.pid} died`)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await this.listen(port, hostname)
|
||||||
|
apiLogger.info(
|
||||||
|
'Started worker %d (worker id %s)', process.pid, process.env.WORKER_ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected async start(
|
protected async start(
|
||||||
port: number | string | undefined = process.env.PORT,
|
port: number | string | undefined = process.env.PORT,
|
||||||
hostname?: string,
|
hostname?: string,
|
||||||
|
|||||||
@ -1,8 +1,28 @@
|
|||||||
import { Bootstrap } from "../application";
|
import { arg, argparse } from '@rondo.dev/argparse'
|
||||||
import { argparse, arg } from "@rondo.dev/argparse";
|
import { cpus } from 'os'
|
||||||
|
import { Bootstrap } from '../application'
|
||||||
|
|
||||||
|
const numberOfCPUs = cpus().length
|
||||||
|
|
||||||
|
const startArgs = {
|
||||||
|
host: arg('string', {
|
||||||
|
description: '',
|
||||||
|
}),
|
||||||
|
socket: arg('number', {
|
||||||
|
alias: 's',
|
||||||
|
description: 'Socket to listen on',
|
||||||
|
}),
|
||||||
|
port: arg('number', {
|
||||||
|
default: 3000,
|
||||||
|
alias: 'p',
|
||||||
|
description: 'Port to listen on',
|
||||||
|
}),
|
||||||
|
help: arg('boolean', {alias: 'h'}),
|
||||||
|
}
|
||||||
|
|
||||||
export function run(bootstrap: Bootstrap, argv: string[]) {
|
export function run(bootstrap: Bootstrap, argv: string[]) {
|
||||||
const choices: Array<keyof typeof commands> = ['start', 'migrate']
|
const choices: Array<keyof typeof commands> = Object
|
||||||
|
.keys(commands) as Array<keyof typeof commands>
|
||||||
const {parse} = argparse({
|
const {parse} = argparse({
|
||||||
command: arg('string', {
|
command: arg('string', {
|
||||||
default: 'start',
|
default: 'start',
|
||||||
@ -24,24 +44,23 @@ export function run(bootstrap: Bootstrap, argv: string[]) {
|
|||||||
|
|
||||||
const commands = {
|
const commands = {
|
||||||
async start(bootstrap: Bootstrap, argv: string[]) {
|
async start(bootstrap: Bootstrap, argv: string[]) {
|
||||||
const {parse} = argparse({
|
const {parse} = argparse(startArgs, 'Start the server')
|
||||||
host: arg('string', {
|
|
||||||
description: '',
|
|
||||||
}),
|
|
||||||
socket: arg('number', {
|
|
||||||
alias: 's',
|
|
||||||
description: 'Socket to listen on',
|
|
||||||
}),
|
|
||||||
port: arg('number', {
|
|
||||||
default: 3000,
|
|
||||||
alias: 'p',
|
|
||||||
description: 'Port to listen on',
|
|
||||||
}),
|
|
||||||
help: arg('boolean', {alias: 'h'}),
|
|
||||||
})
|
|
||||||
const args = parse(argv)
|
const args = parse(argv)
|
||||||
await bootstrap.listen(args.port || args.socket, args.host)
|
await bootstrap.listen(args.port || args.socket, args.host)
|
||||||
},
|
},
|
||||||
|
async cluster(bootstrap: Bootstrap, argv: string[]) {
|
||||||
|
const {parse} = argparse({
|
||||||
|
...startArgs,
|
||||||
|
workers: arg('number', {
|
||||||
|
alias: 'w',
|
||||||
|
description: 'Number of workers to start',
|
||||||
|
default: numberOfCPUs,
|
||||||
|
}),
|
||||||
|
}, 'Start in cluster')
|
||||||
|
const args = parse(argv)
|
||||||
|
await bootstrap
|
||||||
|
.startCluster(args.workers, args.port || args.socket, args.host)
|
||||||
|
},
|
||||||
async migrate(bootstrap: Bootstrap, argv: string[]) {
|
async migrate(bootstrap: Bootstrap, argv: string[]) {
|
||||||
const {parse} = argparse({
|
const {parse} = argparse({
|
||||||
undo: arg('boolean', {
|
undo: arg('boolean', {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user