I’m modernising a 12+ year old PHP code base, and to improve the application performance, I decided to run some tasks asynchronously. It’s notoriously difficult to write asynchronous PHP code, so I took an alternative approach using Beanstalk queues, where a task execution is deferred to a later time. This approach has its pros and cons, but for now it’s good enough for this system.
A worker watches the queue for new jobs, and when those arrive, it processes them. The worker - a simple PHP script - must be run all the time, which can be done in many different ways. The easiest solution would be setting up a cronjob, but it has a few drawbacks (e.g. properly monitoring the tasks, handling script crashes, etc). I thought about using monit or Upstart/Systemd, but it was definitely overkill. Then I got to supervisord: it’s almost as simple as cron, but with many more features.
Installing supervisord
To install supervisord, you must have Python installed. You can install it either via pip
or through a package manager, although these packages tend to be outdated.
pip install supervisor
If you install it using pip
, you will also need to setup a init script. The official repository contains the scripts for the most popular Linux distros.
For Ubuntu, you need to copy the script to /etc/init.d/supervisord
, and then update its permissions:
sudo chmod +x /etc/init.d/supervisord
Next, you need to enable the service:
sudo update-rc.d supervisord defaults
sudo service supervisord start
Configuration
To configure supervisord
, you need to create a new configuration file. supervisord
comes with the echo_supervisord_conf
command, which bootstraps this process:
sudo echo_supervisord_conf > /etc/supervisord.conf
After that, append the following to /etc/supervisord.conf. This setting will inform supervisord
to look for our monitors in the directory /etc/supervisord.d/.
[include]
files=/etc/supervisord.d/*.conf
Then, create the monitors directory:
mkdir -p /etc/supervisord.d/
Finally, create a directory to store the monitors’ logs:
mkdir -p /var/log/supervisord
Process control
Creating a new monitor is trivial - you only need to create a new configuration file and reload supervisord
.
Below is a monitor with very basic settings:
[program:my-queue]
command=php /home/mordor/www/script.php
numprocs=1
numprocs_start=1
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/queue.err.log
stdout_logfile=/var/log/supervisor/queue.out.log
- [program:my-queue]: the program name (it will be used as the display name in
supervisord
). - command: the command
supervisord
will run. - numprocs: the number of instances of the program that we want to run.
- numprocs_start: the number of instances of the program that we want to run at the start of the program.
- autostart: specifies if the process should be automatically started when
supervisord
starts. - autorestart: specifies if the process should be automatically restarted if it exits with an exit code different than 0 or 2.
- stderr_logfile: the path of the stderr log.
- stdout_logfile: the path of the stdout log.
After creating your monitor, you must reload supervisord
by running supervisorctl update
.
Managing processes
supervisord
also provides the supervisorctl
command line utility. All the available commands can be found in the documentation.
Start/stop/restart all workers
supervisorctl [start|stop|restart] all
Start/stop/restart a single worker
supervisorctl [start|stop|restart] <worker>
Reread configs and restart supervisord
supervisorctl update
Monitor status
supervisorctl status