Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

running two instances of gunicorn

Trying to run two sites on gunicorn editing the service from

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/webapps/kenyabuzz

ExecStart=/home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application

[Install]
WantedBy=multi-user.target

to

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/webapps/kenyabuzz
WorkingDirectory=/home/ubuntu/webapps/uganda_buzz

ExecStart=/home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application
ExecStart=/home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/uganda_buzz/ug.sock kb.wsgi:application

[Install]
WantedBy=multi-user.target

the logs shows the ExecStart can't be duplicated

ubuntu@ip-172-31-17-122:~$ sudo systemctl status gunicorn
● gunicorn.service - gunicorn daemon
   Loaded: error (Reason: Invalid argument)
   Active: active (running) since Tue 2017-02-14 09:36:52 EAT; 35s ago
 Main PID: 26150 (gunicorn)
   CGroup: /system.slice/gunicorn.service
           ├─26150 /home/ubuntu/webapps/djangoenv/bin/python /home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application
           ├─26156 /home/ubuntu/webapps/djangoenv/bin/python /home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application
           ├─26157 /home/ubuntu/webapps/djangoenv/bin/python /home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application
           └─26160 /home/ubuntu/webapps/djangoenv/bin/python /home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/kenyabuzz/kb.sock kb.wsgi:application

Feb 14 09:36:52 ip-172-31-17-122 systemd[1]: Started gunicorn daemon.
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26150] [INFO] Starting gunicorn 19.6.0
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26150] [INFO] Listening at: unix:/home/ubuntu/webapps/kenyabuzz/kb.sock (26150)
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26150] [INFO] Using worker: sync
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26156] [INFO] Booting worker with pid: 26156
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26157] [INFO] Booting worker with pid: 26157
Feb 14 09:36:52 ip-172-31-17-122 gunicorn[26150]: [2017-02-14 09:36:52 +0000] [26160] [INFO] Booting worker with pid: 26160
Feb 14 09:37:15 ip-172-31-17-122 systemd[1]: gunicorn.service: Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.

what would be the best way to run two sites in this case, using the available configurations. Tried on the same line separated by space and comma each brings an error.

like image 628
Sam B. Avatar asked Feb 14 '17 06:02

Sam B.


2 Answers

systemd has great support for this situation. I presume you are running a web server like Nginx in front of the apps as a reverse proxy to route traffic to the right endpoint for each Gunicorn instance using their unique socket names. Here I'll focus on the systemd configuration.

It's desirable to be able to stop and start an individual gunicorn instance and also desirable to consider them as a single service that can be stopped or started together.

The systemd solution involves creating a "target" which will be used to treat both instances as a single service. Then, a single "template unit" will be used to allow you to add multiple gunicorns to the "target".

First, /etc/systemd/system/gunicorn.target:

# See README.md for more about this file
[Unit]
Description=Gunicorn
Documentation=https://example.com/path/to/your/docs

[Install]
WantedBy=multi-user.target

That's it. You've created a target that when "enabled" will start at boot. Now /etc/systemd/system/[email protected], the template file:

[Unit]
Description=gunicorn daemon
After=network.target
PartOf=gunicorn.target
# Since systemd 235 reloading target can pass through
ReloadPropagatedFrom=gunicorn.target


[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/webapps/%i

ExecStart=/home/ubuntu/webapps/djangoenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/webapps/%i/kb.sock kb.wsgi:application

[Install]
WantedBy=gunicorn.target

Notice the changes I made to your file:

  1. Each instance is now PartOf= the target.
  2. Enabling this service will make it boot as dependency of the target, due to an updated WantedBy=
  3. The WorkingDirectory= and socket path now use variables, because the file is now a template.

To start or stop all Gunicorn instances at once, we can simply:

systemctl start gunicorn.target
systemctl stop gunicorn.target

We can use enable and disable to add and remove new Gunicorn instances on the fly:

systemctl enable  gunicorn@kenyabuzz
systemctl disable gunicorn@ugandabuzz

We can also stop and start a specific service by itself:

systemctl start gunicorn@kenyabuzz
systemctl stop gunicorn@kenyabuzz
systemctl restart gunicorn@kenyabuzz

The original gunicorn.service file is no longer needed in this pattern and can be removed.

To learn more about any of the system directives used, you can can look at man systemd.directives, which will list the specific man page that documents each directive.

like image 142
Mark Stosberg Avatar answered Nov 04 '22 06:11

Mark Stosberg


If you have two sites, the logical solution would be for each one to be a different service. In this way you can restart one of them, or you can take down one of them for maintenance, without affecting the other.

like image 1
Antonis Christofides Avatar answered Nov 04 '22 04:11

Antonis Christofides