Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

SystemD FastCGI multiple processes

Of late, many mainstream distributions have been switching to Systemd as their init system. This includes Debian (since Debian 8) and Ubuntu (since Ubuntu 15.04). In the traditional SysV init system we used to have stuff like spawn-fcgi or custom scripts for starting a Fastcgi process and having the web server connect to it over Unix or TCP sockets. Such kind of usage decreased when PHP FPM was introduced since it’s safe enough to assume that 90% (probably more) of the FastCGI deployments are just launching PHP interpreters using whatever mechanism is there (spawn-fcgi or custom scripts). PHP FPM does this for you now and it’s pretty good at it.

FastCGI is just a protocol, it can be used by any application. For custom applications which do not support starting their own FastCGI processes and listening on a socket we have to use external mechanisms. SystemD has a couple of good features which can help reduce the amount of custom work needed in terms of process monitoring, socket paths, file ownership, etc.

My use case:

So I installed the support ticketing system called Request Tracker from Best Practical on a server, and initially using spawn-fcgi to start the FastCGI process and nginx to serve the site. I found problems quite fast: spawn-fcgi would create N number of processes which are listening on the given socket, but there’s no re-launching mechanism if the processes die. Applications can crash any time, so we need something to relaunch. The traditional options would have been to use something like a cron job to monitor the PID file or use monit, there are many options. Then I came across this article by the spawn-fcgi people about how to use SystemD to start a FastCGI process.

Once again, a custom script is involved. Digging through SystemD documentation and some more Googling, I was able to get the FastCGI process spawning working using SystemD without any external dependencies (no extra scripts, etc). Here’s how:

[Unit]
Description = Request Tracker FastCGI backend
After = postgresql.service
Wants = postgresql.service

[Service]
User = rt
Group = rt
ExecStart = /usr/local/rt/sbin/rt-server.fcgi
StandardOutput = null
StandardInput = socket
StandardError = null
Restart = always

[Install]
WantedBy = multi-user.target
[Unit]
Description = RT FastCGI Socket

[Socket]
SocketUser = www-data
SocketGroup = www-data
SocketMode = 0660
ListenStream = /run/rt.sock

[Install]
WantedBy = sockets.target

If you do systemctl enable rt-fastcgi.socket && systemctl start rt-fastcgi.socket  then you should have the RT process started up by SystemD when the first request arrives from the web server at /run/rt.sock , and the process keeps running listening for further requests. It gets restarted automatically in case if it crashes or is issued a SIGTERM  manually (which is needed if you make changes to the configuration file).

The problem with this setup:

If you see the difference between this method and the spawn-fcgi method, you will observe that while it is possible to spawn multiple request handlers (i.e. multiple RT processes which can serve the web server) using a single command but the same is not possible with this SystemD method. The daemon being spawned by SystemD must do this extra handling. A single process cannot serve many concurrent requests which is definitely a problem. So let’s use SystemD’s automatic unit files based on per instance feature to make it multiple processes:

[Unit]
Description = Request Tracker FastCGI backend (instance %i)
After = postgresql.service
Wants = postgresql.service

[Service]
User = rt
Group = rt
ExecStart = /usr/local/rt/sbin/rt-server.fcgi
StandardOutput = null
StandardInput = socket
StandardError = null
Restart = always

[Install]
WantedBy = multi-user.target
[Unit]
Description = RT FastCGI Socket (instance %i)

[Socket]
SocketUser = www-data
SocketGroup = www-data
SocketMode = 0660
ListenStream = /run/rt%i.sock

[Install]
WantedBy = sockets.target

What the above setup would do is, listen for requests on multiple sockets at /run/rt%i.sock and spawn the appropriate number of instances. How to use this feature from nginx? Here’s how:

upstream rt_backend {
	server unix:/run/rt1.sock;
	server unix:/run/rt2.sock;
	server unix:/run/rt3.sock;
	server unix:/run/rt4.sock;
	server unix:/run/rt5.sock;
}

server {
# other stuff whatever needed

	location / {
		include fastcgi_params;
		fastcgi_param SCRIPT_NAME "";
		fastcgi_param PATH_INFO $uri;
		#fastcgi_pass unix:/run/rt.sock;
		fastcgi_pass rt_backend;
	}
}

Then just do systemctl enable rt-fastcgi@{1..N}.socket && systemctl start rt-fastcgi@{1..N}.socket , start firing requests from nginx and you should see the number of processes growing because nginx sends requests to the upstream in a Round Robin fashion (which can be changed, of course. Refer to nginx documentation for that).

The post SystemD Fastcgi Multiple Processes appeared first on Nilesh.



This post first appeared on Itech7, please read the originial post: here

Share the post

SystemD FastCGI multiple processes

×

Subscribe to Itech7

Get updates delivered right to your inbox!

Thank you for your subscription

×