Node.js cluster manager


Keywords
cluster, worker, manage, manager, clusters, management, process, cli, app, nodejs, workers
License
MIT
Install
npm install z1@4.1.1

Documentation

z1

z1 is a Node.js cluster management program. It works on Linux Debian, Ubuntu, and other Debian based distributions.

When using Node.js on a web server, one will somehow come to the point where he wants to start multiple processes for one app. The main goal of z1 is to simplify the creation and management of clusters.

Table of contents

Features

The focus of z1 is on simplicity. Therefore it uses the existing package.json of your project and allows you to start your app by typing z1 start in the project folder. z1 also comes with a graceful restart functionality which allows you to restart your cluster without rejecting any request.

Setup

Installation

Via NPM

sudo npm install z1 -g

Note: You might want to run z1 resurrect automatically after rebooting your system. It will start the z1 daemon and all the apps that were running before. (see: install command)

Prepare package.json

Before you can cluster your Node.js app, you need to add a few things to your package.json file.

  1. name - your app name
  2. main - the entry point of your app
  3. ports - an array of port numbers that your app uses
  4. workers (optional) - a number specifying how many workers should be created for your app. The default value is the number of CPU-cores in your system.
  5. output (optional) - a directory for the log and error files. (Default: ~/.z1/<yourAppName>)
  6. devPorts (optional) - ports for development

Important: If you app does not use any ports, you must require z1 in your app and call the z1.ready method.

Example:

{
  "name": "homepage",
  "main": "index.js",
  "ports": [80],
  "workers": 2
}

Development

If you are running z1 locally, you can set the NODE_ENV environment variable to 'development'. This will cause z1 to use the devPorts (if specified) instead of the ports property from the package.json. The default timeout for stop and restart will be set to 0ms.

CLI

Environment variables

You can set different environment variables for each app. The start command automatically applies the environment variables of the current CLI to the app.

export EXAMPLE=hello && z1 start path/to/your/app

There are some environment variables that z1 sets automatically:

  • PORT - the first port
  • PORTS - all ports that z1 listens for (separated by commas)
  • APPNAME - the name of your app
  • PWD - the directory of your app

These variables can not be overwritten.

Start

Starting the app: First go to the directory where the package.json is located. Type the following command into your terminal:

z1 start

In our example the output would be:

name: homepage
workers started: 2

options

If you want to start your app with different settings than the ones specified in the package.json, you can add them to to the z1 start command.

--name anotherName
--ports 80,2020,8080
--workers 4
--output path/to/logs/

Restart

You can restart your app to apply updates for your app or changes to the package.json. The restart process will be gapless and no requests will be refused. Just type the following command:

z1 restart homepage

The first argument for the z1 restart command is the app name that was in the package.json when you started the app.

Output of the example from above:

name: homepage
workers started: 2
workers killed: 2

options

--timeout 10000

--timeout is a number specifying the maximal time that the old workers are allowed to run after they are killed (in ms). The default value is 30000 (30s). If you set it to "infinity" the old processes might run forever.

List

z1 list

Displays a list of all running apps.

Example:

 workers name                 ports
 0  2  0 homepage             80
 |  |  |
 |  | killed
 | available
pending
  1. Pending - processes are currently starting.
  2. Available - workers are listening to all the ports specified in the package.json
  3. Killed - workers are not listening for new connections. They will finish their outstanding requests before they exit.

Info

z1 info exampleApp

Shows more detailed information than z1 list.

Example output:

name: exampleApp
directory: path/to/your/app
ports: 80
workers:
  pending: 0
  available: 2
  killed: 0
revive count: 0

Stop

To stop an app just type:

z1 stop homepage

Example output:

name: homepage
workers killed: 2

options

--timeout 10000

--timeout is a number specifying the maximal time that the workers are allowed to run after they are killed (in ms). The default value is 30,000ms. If you set it to "infinity" the old processes might run forever.

Exit

z1 exit

Will kill the z1 daemon process and therefore all apps and workers.

Resurrect

After you typed exit, you can use the following to start all the apps that were running before:

z1 resurrect

Note: If you are starting a new app before z1 resurrect, the old apps will not be restored.

Install and Uninstall

This command allows you to add and remove additional features.

  1. zsh - shell completion for zsh
  2. bash - shell completion for bash (coming soon)
  3. cron - cron job that resurrects z1 after a reboot
sudo z1 install zsh

Passing arguments to workers

You can start your app with custom arguments.

z1 start --name 'custom app' --ports 80 -- hello

This would start an app with the name 'custom app' that is listening on port 80. Everything behind the -- will be passed to the workers. In your code you can get the "hello" as argv.

process.argv[2] === 'hello' // true

API

Besides the CLI, you can also require z1 to control your apps with a Node.js program.

const z1 = require('z1')

z1.start(dir, args, opt, env, immediate)

Arguments

  • dir <String> - Path to the directory where the package.json of the app is located (Default: current directory)
  • args <Array> (optional) - Arguments for the workers
  • opt <Object> (optional) - Options that overwrite the ones from the package.json
  • env <Object> (optional) - Key-value-pairs to be added to process.env in the workers.
  • immediate <Boolean> (optional) (Default: false)

Returns a <Promise> that gets resolved when the app is started. If you set immediate to true, the promise gets resolved immediately after your command was transmitted to the daemon.

By default It resolves to an object with the following data:

{
  app: String,
  dir: String,
  started: Number
}
  • app - The name of the app specified in the package.json. You will need this in order to restart/stop the app.
  • dir - Absolute path to the directory where the package.json is located
  • started - Number of workers started for this app

z1.restart(app, opt)

Arguments

  • app <String> - The name specified in the package.json of the app you want to restart.
  • opt <Object> - (optional)
    • timeout <Number> - Maximum time until the old workers get killed (default: 30000ms).
    • signal <String> - Kill signal for the old workers

Returns a <Promise> that gets resolved when the new workers are available and the old ones are killed. It resolves to an object with the following data:

{
  app: String,
  dir: String,
  started: Number,
  killed: Number
}
  • app - the app name
  • dir - directory of the app
  • started - Number of started workers
  • killed - Number of killed workers

z1.stop(app, opt)

Arguments

  • app <String> The name specified in the package.json of the app you want to restart.
  • opt <Object> (optional)
    • timeout <Number> Maximum time until the old workers get killed (default: 30000ms).
    • signal <String> Kill signal

Returns a <Promise> that gets resolved when the old workers are killed. It resolves to an object with the following data:

{
  app: String,
  killed: Number
}
  • app - the app name
  • killed - Number of killed workers

z1.info(app)

Arguments

  • app <String> The name of your app.

Returns a <Promise> that gets resolved to an object that contains information about the app.

Example:

{
  name: 'homepage',
  reviveCount: 0,
  ports: [80],
  pending: 0,
  available: 2,
  killed: 0
}

z1.list()

Returns a <Promise> that resolves to an object containing data about all running workers.

You can access the data for an app by using the name as key:

z1.list().then(data => {
  console.log(data.stats)
})

The output would be:

{
  homepage: {
    dir: '/home/user/apps/homepage',
    ports: [80],
    pending: 0,
    available: 2,
    killed: 0
  }
}

z1.exit()

Returns a <Promise> that resolves to an empty object. It gets resolves after the z1 daemon has exited.

z1.resurrect()

Returns a <Promise> that resolves to an object.

Example:

{
  started: 2 // two workers started
}

It will be rejected if z1.resurrect() or z1.start() was called before.

Resurrect will start all apps that were running before the daemon was killed.

z1.ready()

Returns a <Promise> that resolves when the ready signal has been transmitted.

This function must be called if an app does not use any port. It will tell the z1 daemon that your app has been started successfully.

Example:

const z1 = require('z1')

// ...your program...

z1.ready()