Apache mod_wsgi: demystifying WSGIApplicationGroup

Summary

WSGIApplicationGroup is a name of the Python sub-interpreter. You don’t need sub-interpreters if you run mod_wsgi in daemon mode (i.e. with dedicated processes). Always set WSGIApplicationGroup to %{GLOBAL}. If you have multiple applications, use <Location> tag in your site configuration, as follows:

WSGIDaemonProcess app_one processes=2 threads=15 display-name=%{GROUP}
WSGIScriptAlias /api/wsgi/one /var/www/mysite/api/one/wsgi.py

<Location /api/wsgi/one>
  WSGIProcessGroup app_one
  WSGIApplicationGroup %{GLOBAL}
</Location>

WSGIDaemonProcess app_two processes=2 threads=15 display-name=%{GROUP}
WSGIScriptAlias /api/wsgi/two /var/www/mysite/api/two/wsgi.py

<Location /api/wsgi/two>
  WSGIProcessGroup app_two
  WSGIApplicationGroup %{GLOBAL}
</Location>

More details

I am experimenting with running WSGI apps, and my server is Apache. There seems to be a lot of debate how to run Flask apps properly:

  • Using nginx + gunicorn
  • Using Apache + mod_wsgi
  • Using Apache + gunicorn (yes, it’s possible)

Since I already have Apache, using mod_wsgi seems like a natural choice, but there are some caveats, especially if you run multiple applications.

To the best of my understanding, the following rules apply.

You define your application(s) using WSGIScriptAlias directive in the site config file. This is relatively straightforward.

You define one or more pools of WSGI “daemons” using WSGIDaemonProcess directive.

You tell Apache which application runs in which daemon pool via WSGIProcessGroup directive. You must use the
<Location> tag to differentiate between different applications, as shown in the example above.

You then tell Apache which Python sub-interpreter you want to use for your processing. When you are running inside a dedicated process,
there is no point using a sub-interpreter, so the specification is WSGIApplicationGroup %{GLOBAL}. In particular, numpy doesn’t
like sub-interpreters and prints a warning like this:

UserWarning: NumPy was imported from a Python sub-interpreter but NumPy does not properly support sub-interpreters.
This will likely work for most users but might cause hard to track down issues or subtle bugs.
A common user of the rare sub-interpreter feature is wsgi which also allows single-interpreter mode.
Improvements in the case of bugs are welcome, but is not on the NumPy roadmap, 
and full support may require significant effort to achieve.

In general, mod_wsgi works well, but its defaults are targeted towards the old use case, when the requests
were handled in the main Apache process, and each application used its own Python sub-interpreter. You must explicitly
specify the process pool and the “global” sub-interpreter for each application. This makes the configuration somewhat
verbose, but once you know what you’re doing it is not a big deal.

Leave a Reply

Your email address will not be published. Required fields are marked *