Apache2 mod_wsgi C module (@GrahamDumpleton)

Graham Dumpleton

../../../../../_images/graham_dumpleton.jpg

Introduction

Apache/mod_wsgi has traditionally been seen as a deployment target only for production systems.

To use it in a development environment is viewed as too difficult and not worth the trouble. The downside of not using Apache/mod_wsgi in a development environment when ultimately deploying to it in production, and instead using a development server provided by any web framework being used, is that situations can arise where your application may work fine in development but then fail in production

En français

Le concept principal de WSGI est d’utiliser un objet appelable, fonction ou méthode, appelée application .

Cet objet sert à assurer les communications entre le serveur WSGI et votre code.

Il est de convention que cet objet s’appelle application .

Important facts

Warning

Important to realise though is that mod_wsgi is compiled against a specific Python version.

Although you can change PYTHONHOME effectively used, you can only refer it to Python virtual environment based on the same Python installation that mod_wsgi was compiled for.

Modes of Operation

When hosting WSGI applications using mod_wsgi, one of two primary modes of operation can be used.

In ‘embedded’ mode, mod_wsgi works in a similar way to mod_python in that the Python application code will be executed within the context of the normal Apache child processes.

WSGI applications when run in this mode will therefore share the same processes as other Apache hosted applications using Apache modules for PHP and Perl.

An alternate mode of operation available with Apache 2.X on UNIX is ‘daemon’ mode. This mode operates in similar ways to FASTCGI/SCGI solutions, whereby distinct processes can be dedicated to run a WSGI application. Unlike FASTCGI/SCGI solutions however, neither a separate process supervisor or WSGI adapter is needed when implementing the WSGI application and everything is handled automatically by mod_wsgi.

Because the WSGI applications in daemon mode are being run in their own processes, the impact on the normal Apache child processes used to serve up static files and host applications using Apache modules for PHP, Perl or some other language is much reduced. Daemon processes may if required also be run as a distinct user ensuring that WSGI applications cannot interfere with each other or access information they shouldn’t be able to.

Note that although mod_wsgi has features similar to FASTCGI/SCGI solutions, it isn’t intended to be a replacement for those hosting mechanisms in all situations for Python web hosting. Specifically, mod_wsgi is not designed for nor intended for use in over allocated shared mass virtual hosting setups for different users on a single Apache instance.

For such mass virtual hosting arrangements, FASTCGI in particular would still be the preferred choice in most situations.

Server Performance

The mod_wsgi module is written in C code directly against the internal Apache and Python application programming interfaces. As such, for hosting WSGI applications in conjunction with Apache it has a lower memory overhead and performs better than existing WSGI adapters for mod_python or alternative FASTCGI/SCGI/CGI or proxy based solutions.

Although embedded mode can technically perform better, daemon mode would generally be the safest choice to use .

This is because to get the best performance out of embedded mode you must tune the Apache MPM settings, which in their default settings are biased towards serving of static media and hosting of PHP applications .

If the Apache MPM settings are not set appropriately for the type of application being hosted, then worse performance can be seen rather than better performance.

Thus, unless you are adept at configuring Apache, always use daemon mode when available. Overall, for large Python web applications you wouldn’t normally expect to see any significant difference between daemon mode and embedded mode, as the bottlenecks are going to be in the Python web application or any database access.

Conseils pour la configuration du serveur virtuel

The apache configuration files must have, at a minimum, a mod_wsgi WSGIScriptAlias directive directive.

There is also a list of the apache modules which get loaded, and mod_wsgi must be included.

mod_wsgi must be linked against the particular apache, but the distribution, if you’re using the OS’s package manager, should have made sure of that.

As previously mentioned by another, mod_wsgi is linked against a particular python interpreter. Again, hopefully the OS package manager pulls in stuff built to work together, but this does mean that you can’t, say, use python2.7 if the distribution’s python is a 2.6.

It is much to be preferred, though not absolutely required, that the python in question was build after passing “–enable-shared” to the configure script. Unless you build everything yourself (which I usually do, but not yet on Raspberry PI), you have no control of this.

That mod_wsgi WSGIScriptAlias directive directive should probably specify a python-path argument specifying the directory with manage.py in it, though I’ve seen it work with the adding of this path deferred to the wsgi script python module.

You can use a virtualenv, but it must have been made with the python interpreter against which mod_wsgi is linked (not the same file, but ve/bin/python is generally a copy, and this works well enough), but you will either need to use the WSGIPythonHome directive, or, if your mod_wsgi is new enough, the python-home argument of the WSGIScriptAlias directive.

(The advantage of the latter is the ability to use separate virtualenvs in separate VirtualHosts, whereas WSGIPythonHome is global across all mod_wsgi daemon processes under a single apache..)

You will want to configure Alias directives to allow serving your STATIC and MEDIA files at the expected URLs.

You will need a number of Directory directives (though fewer than some people think).

Python Virtual Environments (VE’s) under Apache

Virtual environments can, indeed, be used under Apache. I presume other front ends can also handle this.

For Apache, the separate VE’s need to be in separate deamon process groups, so that their sys.path settings can differ.

The primary thing that virtualenv does for you is tweak sys.path, usually by setting PYTHONHOME, but there are other ways.

If using a new enough mod_wsgi (3.4 or later, I think), there is a python-home option to the WSGIDaemonProcess directive.

Otherwise you can fiddle sys.path in your wsgi script file.

If you are using Apache/mod_wsgi, there is lots of useful documentation and a pointer to their mailing list at http://code.google.com/p/modwsgi/

Warning

but each python must have been made with the python interpreter against which mod_wsgi is linked

Daemon mode versus embedded mode

When using mod_wsgi , by default any hosted WSGI application will run in what is called embedded mode.

Although this is the default, if you are running on a UNIX system it is highly recommended you do not use embedded mode and instead use what is called daemon mode.

The difference is that with embedded mode, the WSGI application runs inside of the Apache child worker processes. These are the same processes which handle any requests received by Apache for serving up static files. Using embedded mode can result in various issues due to the way Apache manages those processes.

The best solution is simply not to use embedded mode and use daemon mode instead .

Warning

Le “Daemon mode” n’est pas disponible sous Windows.

Serving up of static files

Although we can use the WSGI application code used for this test to serve up static files, in general, serving up static files from a WSGI application is a bad idea.

This is because the overheads will still be significantly more than serving up the static files from a proper web server.

Daemon mode , python-home au lieu de python-path

If using daemon mode of mod_wsgi you would use the ‘python-path’ option to the WSGIDaemonProcess directive:

WSGIDaemonProcess pylons python-path=/usr/local/pythonenv/PYLONS-1/lib/python2.5/site-packages

What was ugly about this was that you had to refer to the ‘site-packages’ directory where it existed down in the Python virtual environment. That directory name also included the Python version, so if you ever changed what Python version you were using, you had to remember to go change the configuration.

The good news is that since mod_wsgi version 3.4 or later there is a better way.

Rather than fiddling with what goes into ‘sys.path’ using the ‘WSGIPythonPath’ directive or the ‘python-path’ option to ‘WSGIDaemonProcess’, you can use the ‘python-home’ option on the ‘WSGIDaemonProcess’ directive itself.:

WSGIDaemonProcess pylons python-home=/usr/local/pythonenv/PYLONS-1

As when using the ‘WSGIPythonHome’ directive, this should be the top level directory of the Python virtual environment you wish to use. In this case the value will only be used for this specific mod_wsgi daemon process group.

If you are therefore using a new enough mod_wsgi version, and using mod_wsgi daemon mode, then switch to the ‘python-home’ option of ‘WSGIDaemonProcess’.

Explication

If you have only one wsgi script on that Apache, you might consider the WSGIPythonHome directive (the directive must be global, rather than in a vhost, thus there can be only one).

Or, if you have a new enough mod_wsgi, the WSGIDaemonProcess directive also takes a “python-home” argument (I do have three or four ve’s (virtual environments) running on one Apache this way).

Daemon mode , python-home et home

In using the ‘home’ option the way it has worked in the past is that it only set the current working directory. This changed though in mod_wsgi 4.1.0 such that modules will be searched for automatically in that directory as well.

This means that from mod_wsgi 4.1.0 onwards you can actually simplify the options for daemon mode to:

WSGIDaemonProcess example home=/path/to/mysite.com

Combining this with a Python virtual environment which you want to use just for that daemon process group, you would use:

WSGIDaemonProcess example python-home=/path/to/venv home=/path/to/mysite.com

Daemon mode WSGIRestrictEmbedded , mod_wsgi version 3.4

The generated wsgi.py file should be fine, you can do all the path setup from mod_wsgi.

A reasonable configuration if using mod_wsgi 3.4 would be::

WSGIDaemonProcess example.com python-home=/path/to/your/venv python-path=/path/to/mysite.com
WSGIProcessGroup example.com
WSGIApplicationGroup %{GLOBAL}
WSGIRestrictEmbedded On

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

This is mostly covered in https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/modwsgi/

with the exception that using python-home in this example.

The WSGIRestrictEmbedded directive turns off Python in the Apache worker processes since you are using a daemon process group. Saves on memory and CPU startup cost of worker processes.

The WSGIApplicationGroup with value %{GLOBAL} for daemon process forces use of main interpreter, avoiding creation of a second sub interpreter context and avoids issues with some third party C extension modules which do not work properly in sub interpreters.

L’application WSGI Django

Variables d’environnement

mod_wsgi directives

mod_wsgi on GNU/Linux

mod_wsgi on Windows

mod_wsgi_express

mod_wsgi versions