Using static FastCGI when dynamic is all that's available
- dynamic FastCGI
- When FastCGI applications are launched and managed by the web server. Pro: Easier to manage. Cons: No guarantee that your application will only be launched once (i.e. it must be multi-process safe). Depending on how slow your application starts, the web server may end up starting many instances. When developing an application, unless your web server starts the process as yourself, it takes more work to kill/restart your application (if even possible).
- static FastCGI
- When the web server connects to an externally- and typically manually-launched FastCGI application via a socket. Pro: You control exactly how many instances of your application runs. Cons: If you want your application to always be up, you will need to set up some way to start it in case it dies or the machine reboots. (Not covered here.)
In case you are ever stuck with only dynamic FastCGI, there's a way to manage your FastCGI applications as if they were static. Note that this probably only matters if you are in a shared hosting environment. I assume if you are managing/running your own server (i.e. you have root), you can configure mod_fastcgi/lighttpd/whatever to connect directly to static FastCGI applications. Also note that running servers (basically any long-running user process that listens on a socket) may be against your host's TOS, so please check first before trying any of this.
First, set up the dynamic FastCGI "stub":
#!/your/python from flup.client.scgi_app import SCGIApp from flup.server.fcgi import WSGIServer # You may also use fcgi_fork app = SCGIApp(connect='/path/to/your/home/dir/myapp.sock') WSGIServer(app).run()
Put this where you would normally put your application's FastCGI runner, for example, as ~public_html/wiki.fcgi. Make sure the hash-bang line actually reflects the location of Python and that the script is executable.
Next, simply wire up your application as if it was connecting via SCGI:
import logging from myapp import app # Application object from flup.server.scgi import WSGIServer # Use threaded or forking, depending on your app WSGIServer(app, scriptName='', # Adjust this to reflect the relative path of your app bindAddress='/path/to/your/home/dir/myapp.sock', umask=0, loggingLevel=logging.WARN).run()
Launch this script yourself. You may want to run it in the background and/or redirect stdout to a log file.
And that's it! Using the previous example, connections to http://yourdomain.com/wiki.fcgi will connect to your application.
Frequently Asked Questions
Isn't this inefficient?
Yes. But how inefficient I've yet to determine. ;) Also, since the extra hop occurs over a UNIX domain socket, I hope it really isn't all that slow.
I get "permission denied" errors from the stub
Make sure the web server's user can read/write to your socket (the '/path/to/your/home/dir/myapp.sock' above). Also adjust the umask accordingly. It is set to 0 above to allow everyone to read/write from/to the socket. Unfortunately, this might be necessary if you have no groups in common with the web server user.