lighty's life

lighty developer blog

How to Spawn a Backend Process

I'm not completly sure yet how I will add the spawning of processes to the new mod_proxy_core. The current idea is mod_spawn described as below. If you have specific needs or ideas how to implement it, add your comment please. Before we had mod_proxy_core mod_fastcgi, mod_scgi and mod_proxy were all doing the same with just a different protocol. We fixed that. How about mod_cgi ? It is a bit different as it uses pipes for the communitcation and the process envirionment to pass the CGI-environment. But otherwise it works the same. mod_proxy_core doesn't care about spawning processes, it is a proxy mode. Data in, data out. Some transformation in between. But we need processes. CGI needs a new one for each request, FastCGI and SCGI like to keep them up all the time. Some like user changes, some have to restarted when they die. In the end it is independent of the protocol. If you take a step back the process spawning looks like this:

Communication channel

* FastCGI, SCGI and HTTP use sockets. Either TCP or Unix-Domain * CGI uses 2 pipes

Number of requests before shutdown

* CGI terminates at the end of the request, no restart * The other perfer to stay alive All have to be started before we can communicate with them.

Possible Configuration

I thought about how to configure the spawning and came up with this:
## FastCGI spawning
$HTTP["url"] =~ ".php$" {
  var.backends = ( "127.0.0.1:1026", "127.0.0.1:1027" )

  spawn.bin-path = "/usr/bin/php-cgi"
  spawn.socket-type = "socket"
  spawn.socket-name = var.backends
  spawn.environment = ( "PHP_FCGI_CHILDREN" => "16" )
  ## terminate the number of requests to the process to 1000 
  spawn.max-requests = 1000

  proxy-core.protocol = "fastcgi" 
  proxy-core.backends = var.backends
}
We spawn one PHP process with 16 worker processes listening on the TCP-socket 127.0.0.1:1026. As this a socket-based process we keep it alive automaticly. We might add some fine-tuning if want to start the process when we need it or keep it running all the time. For shared-hosting environments it might make sense to keep them down to safe memory. For CGI it looks similar. We have a spawn.environment to pass variables to the process environment, we have a bin-path to call a interpreter for a script, ...
## CGI spawning, self-executing
# old
$HTTP["url"] =~ "^/cgi-bin/" {
  cgi.assign = ( "" => "" )
}
# new
$HTTP["url"] =~ "^/cgi-bin/" {
  spawn.socket-type = "pipe"
  spawn.environment = ( "TRAC_ENV" => "lighttpd" )

  proxy-core.protocol = "cgi"
}

## Perl-CGIs
# old
cgi.assign = ( ".pl" => "/usr/bin/perl" )
# new
$HTTP["url"] =~ "\.pl$" {
  spawn.bin-path = "/usr/bin/perl -wT"
  spawn.socket-type = "pipe"

  proxy-core.protocol = "cgi" 
}

Why ?

Why all this new stuff ? Because we have alot code-duplication and sorting this out is just a good idea. Especially for the windows port of the CGI code we need a central place to spawn a process.

How about the old mod_fastcgi

I think all the old modules (mod_fastcgi, mod_scgi, mod_cgi, mod_proxy) will be deprecated in 1.5.0. Their code is in different modules now and none of the will be needed. But removing them would scare away all current users. The plan is to turn all those modules into frontend modules to mod_proxy_core instead. They will maintain the old configuration syntax but will push the config down to the mod_proxy_core and mod_spawn instead.

And suEXEC ?

suexec only needs spawn.bin-path and the spawn.environment to work. It will work for all backend processes and not just for FastCGI as now.

And now ?

Now, I need your comments. Does this make sense ? What is missing from this idea ?