Unitech / pm2

Node.js Production Process Manager with a built-in Load Balancer.
https://pm2.keymetrics.io/docs/usage/quick-start/
Other
41.42k stars 2.62k forks source link

Multiple instance of an app (in fork mode) bound to different ports + load balancing using nginx #765

Closed zeusdeux closed 9 years ago

zeusdeux commented 10 years ago

So this isn't an issue per se but I haven't been able to find data on this and would appreciate the help.

The idea is to run multiple instance of the same app (in fork mode) bound to different ports using pm2, on a single machine. The requests to these apps will be load balanced using nginx as a reverse proxy.

I run the first instance using the following command:

APP_PORT=3000 pm2 start -x ./bin/server --name "app1"

This works fine. But when I do:

APP_PORT=4000 pm2 start -x ./bin/server --name "app2"

I get an error saying:

[PM2] [ERROR] Script already launched, add -f option to force re execution

How do I start multiple instances of the same app bound to different ports on a the same machine using pm2?

Thanks in advance!

jfhenriques commented 9 years ago

If you can live without any feature of pm2, such as monitoring, etc, I would launch each instance isolated from each other (without fork), and use supervisord instead of pm2.

Just my two cents.

zeusdeux commented 9 years ago

If pm2 is incapable of meeting this requirement then I will be switching to a solution like supervisord or monit etc.

The reason I asked this here is because this is a basic requirement when setting up a bunch of instances of a node app to be load balanced by nginx. I know that pm2 can manage load balancing using the cluster module but imho cluster needs a lot of work still and isn't production ready yet.

So yes, if pm2 cannot deliver then supervisord or monit it shall be but I really hope there's a way to do this in pm2.

faizanahemad commented 9 years ago

Facing same issue, though I am using pm2 with cluster mode in production (my application is small). But the problem I face is IF my node servers fail nginx can show a custom page (pages like Sorry we ll be back). But if I use pm2 I can find no way to do this.

skozin commented 9 years ago

I was able to launch multiple instances of the same script using json config:

pm2 start pm2.json

pm2.json:

{
  "apps": [
    {
      "exec_mode": "fork_mode",
      "script": "./lib/index.js",
      "name": "proj-0",
      "node_args": [ "--harmony" ],
      "env": {
        "PORT": 4001,
        "NODE_ENV": "production"
      },
      "error_file": "/var/www/logs/proj-0.err.log",
      "out_file": "/var/www/logs/proj-0.out.log"
    },
    {
      "exec_mode": "fork_mode",
      "script": "./lib/index.js",
      "name": "proj-1",
      "node_args": [ "--harmony" ],
      "env": {
        "PORT": 4002,
        "NODE_ENV": "production"
      },
      "error_file": "/var/www/logs/proj-1.err.log",
      "out_file": "/var/www/logs/proj-1.out.log"
    }
  ]
}
Unitech commented 9 years ago

Json is always a better way to declare how your apps should be configured!

With PM2 0.12 you will be able to write json with json5

Closing

zeusdeux commented 9 years ago

Right, I shall try this. Ty @skozin

@Unitech advice taken. And, json5 seems nice but that site has to be one of the most unreadable sites I have come across in a while haha.

dtouch3d commented 9 years ago

@Unitech Can you please elaborate on json5 and how it affects this issue ? I can't find anything like repeating the same config block over and over again with slight variations, as this is what is usually needed in these cases.

matt212 commented 8 years ago

Hi, I am new to nginx and i wanted to load balance my nodejs webapp using nginx and there are various confusing articles about it , is there any stream line walkthrough for nginx + nodejs webapps in localhost based system ? pm2 clustering is good but when i perform apache benchmark test the result for static content are poor ! cluster screen grab screenshot from 2016-02-27 17 57 27 and apache benchmark screenshot new

ChStark commented 8 years ago

one workaround that surprisingly worked for me is creating symlinks

Zaggen commented 7 years ago

I personally run multiple instances of my app in different ports with pm2, i name the instance after the port, like 'myapp:8080' and i have a js loadbalancer and the nginx on lets say por 1337, then the nginx forwards the traffic from the port 80 and serves the static files.

pm2

This is the load balancer i created for that, it uses redis to register and unregister servers, feel free to use it.

https://gist.github.com/Zaggen/bbec82153f45ec60a136dca8e9ed65e7

And the nginx config file looks something like this:

server {
  listen 80;
  listen [::]:80 ipv6only=on;

  root /var/www/my-app/.tmp/public;

  server_name "";

  location / {
     try_files $uri @backend;
  }

  location @backend {
     proxy_pass http://127.0.0.1:1337;
     proxy_http_version 1.1;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     # Following is necessary for Websocket support
     proxy_cache_bypass $http_upgrade;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
   }
}
pinich commented 7 years ago

Here is a really useful tutorial on how to implement clustering in PM2 https://keymetrics.io/2015/03/26/pm2-clustering-made-easy/

🔢

lid3rs commented 5 years ago

I was able to launch multiple instances of the same script using json config:

pm2 start pm2.json

pm2.json:

{
  "apps": [
    {
      "exec_mode": "fork_mode",
      "script": "./lib/index.js",
      "name": "proj-0",
      "node_args": [ "--harmony" ],
      "env": {
        "PORT": 4001,
        "NODE_ENV": "production"
      },
      "error_file": "/var/www/logs/proj-0.err.log",
      "out_file": "/var/www/logs/proj-0.out.log"
    },
    {
      "exec_mode": "fork_mode",
      "script": "./lib/index.js",
      "name": "proj-1",
      "node_args": [ "--harmony" ],
      "env": {
        "PORT": 4002,
        "NODE_ENV": "production"
      },
      "error_file": "/var/www/logs/proj-1.err.log",
      "out_file": "/var/www/logs/proj-1.out.log"
    }
  ]
}

Optimised your answer:

// Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
const app = {
    name: "App",
    script: "server.js",
    args: "one two",
    instance_var: "INSTANCE_ID",
    log_date_format: "YYYY-MM-DD HH:mm Z",
    autorestart: true,
    max_memory_restart: "1G"
};

module.exports = {
    apps: [
        {
            ...app,
            ...{
                watch: false,
                env: {
                    PORT: 5000,
                    NODE_ENV: "production"
                }
            }
        },
        {
            ...app,
            ...{
                watch: true,
                env: {
                    PORT: 5001,
                    NODE_CONFIG_DIR: "",
                    NODE_ENV: "staging"
                }
            }
        }
    ],

    deploy: {
        production: {
            user: "node",
            host: "212.83.163.1",
            ref: "origin/master",
            repo: "git@github.com:repo.git",
            path: "/var/www/production",
            "post-deploy": "npm install && pm2 reload ecosystem.config.js --env production"
        }
    }
};