I have been messing around with Django over the past week and experimenting with various settings. I first ran Django using mod_ptyhon from Apache but the results were unimpressive. Apache served the Django project’s pages extremely slow using the Apache mod_python module. After some reading I decided to give the Apache mod_fastcgi module a try to see if the results were any better. I was definitely happier with the web page load time so I then decided to experiment with various FastCGI settings.
One of the items I played around with was running FastCGI preforked from a socket or FastCGI threaded using a TCP port. I eventually settled on using the TCP port because it was easier for my current scenario. I was able to locate a bunch of different Linux init scripts running a preforked FastCGI server on a Unix domain socket however I was unable to locate a Linux init script running a threaded FastCGI server on a TCP port. Below is what I ended up with after looking over some of the different init scripts available for the preforked FastCGI server.
Init Script To Run A Django Projects Threaded FastCGI Server On A TCP Port:
- #!/bin/sh
- #
- # chkconfig: 345 85 15
- # description: FastCGI server for Django
- # Source function library
- . /etc/rc.d/init.d/functions
- # Source networking configuration.
- . /etc/sysconfig/network
- # Check that networking is up.
- [ "${NETWORKING}" = "no" ] && exit 0
- PROJECT=project-name # django project name
- PROJECTPATH=/path/to/project # path to the django project
- HOST=127.0.0.1 # host to bind the port to
- PORT=3033 # port to listen on
- PIDPATH=/var/run # .pid file location
- RUNASUSER=root # user to run fastcgi
- SERVERNAME=fcgi-$PROJECT # Process name
- # Maximum requests for a child to service before expiring
- #MAXREQ=
- # Spawning method - prefork or threaded
- METHOD=threaded
- # Maximum number of children to have idle
- #MAXSPARE=
- # Minimum number of children to have idle
- #MINSPARE=
- # Maximum number of children to spawn
- #MAXCHILDREN=
- start () {
- # Check if the service is already running?
- if [ ! -f $PIDSPATH/$SERVERNAME.pid ]; then
- echo -n $"Starting $SERVERNAME..."
- daemon --user $RUNASUSER $PROJECTPATH/manage.py runfcgi pidfile=$PIDPATH/$SERVERNAME.pid \
- ${HOST:+host=$HOST} \
- ${PORT:+port=$PORT} \
- ${MAXREQ:+maxrequests=$MAXREQ} \
- ${METHOD:+method=$METHOD} \
- ${MAXSPARE:+maxspare=$MAXSPARE} \
- ${MINSPARE:+minspare=$MINSPARE} \
- ${MAXCHILDREN:+maxchildren=$MAXCHILDREN} \
- ${DAEMONISE:+damonize=True}
- echo
- RETVAL=$?
- else
- echo $"$SERVERNAME is already running."
- fi
- }
- stop() {
- # Stop daemons.
- if [ -f $PIDPATH/$SERVERNAME.pid ]; then
- echo -n $"Stopping $SERVERNAME..."
- killproc -p "$PIDPATH/$SERVERNAME.pid" -d 60 $SERVERNAME
- echo
- # Delete pidfile only when Django was called successfully
- if [ $? -eq 0 ]; then
- rm -f $PIDPATH/$SERVERNAME.pid "$SERVERNAME.pid" >/dev/null 2>&1
- fi
- else
- echo $"$SERVERNAME is NOT running."
- fi
- }
- RETVAL=0
- case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p "$PIDPATH/$SERVERNAME.pid" $SERVERNAME
- RETVAL=$?
- ;;
- restart)
- stop
- start
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|status}"
- exit 3
- ;;
- esac
- exit $RETVAL
After you install the script and verify it is operational you can make sure that your FastCGI init script starts when the server reboots by using chkconfig. The command below will add fastcgi for the default server runlevels.
Add Django Project FastCGI Server To Runlevel Services:
- [root@dev init.d]# chkconfig fastcgi-project on
- [root@dev init.d]# chkconfig --list | grep fastcgi
- fastcgi-project 0:off 1:off 2:on 3:on 4:on 5:on 6:off
FastCGI Init Script Django Project Variables:
At a minimum you will need to change PROJECT and PROJECTPATH. PROJECT is the variable for the name of the project and will be used to name the PID file in /var/run and other things. The PROJECTPATH is important because that is the actual location of the manage.py file that will launch the FCGI(FastCGI) server.
FastCGI Init Script Linux Variables:
The settings in the top of the init script are based off of CentOS Linux but should be similar for many different Linux distros. Make sure to verify “/etc/rc.d/init.d/functions” and “/etc/sysconfig/network” to make sure those are the correct locations for your version of Linux.
That is really all there is to it. If you have multiple Django projects you can create different init scripts for each one if necessary. Below are a couple examples of the init script being started, stopped, restarted, and providing a status of the FCGI server. In the examples below the init script was named fcgi-project and the Django project is simply called project.
Django Project FastCGI Server Being Started Using Init Script:
- [root@dev init.d]# /etc/init.d/fastcgi-project start
- Starting fcgi-project...[ OK ]
Django Project FastCGI Server Being Stopped Using Init Script:
- [root@dev init.d]# /etc/init.d/fastcgi-project stop
- Stopping fcgi-project...[ OK ]
Django Project FastCGI Server Being Restarted Using Init Script:
- [root@dev init.d]# /etc/init.d/fastcgi-project restart
- Stopping fcgi-project...[ OK ]
- Starting fcgi-project...[ OK ]
Django Project FastCGI Server Providing A Status Of Running Using Init Script:
- [root@dev init.d]# /etc/init.d/fastcgi-project status
- fcgi-project (pid 26426) is running...
Django Project FastCGI Server Providing A Status Of Stopped Using Init Script:
- [root@dev init.d]# /etc/init.d/fastcgi-project status
- fcgi-project is stopped
Django seems really cool so far. I would suggest that if you are serving a Django project using Apache that you at least consider using FastCGI servers to do so. I found out fairly quick that mod_python is a beast compared to mod_fastcgi.