Multiple mod_wsgi apps on one virtual host directing to wrong app

25,299

Solution 1

I've had multiple WSGI apps running on a single Apache install, and found that the easiest thing to do is just have multiple process groups-- one for each of the apps.

One downside, versus actually trying to get a single process to run both (or more) apps, is that this might use a little more resident memory than you could get away with otherwise. But it keeps them pretty well separated and avoids hassle. And that might not be a concern for you (it wasn't for me).

(It might not be that bad either, they might be able to share a lot of text pages? That's just idle speculation; I haven't verified this in any way, as my setup was not at all memory-starved)

Here's some snippets of my httpd.conf, approximately:

WSGIDaemonProcess khdx_wsgi user=galdosd group=galdosd maximum-requests=10000
WSGIScriptAlias /khdx /home/galdosd/khdxweb/rel/khdx/apache/django.wsgi
<Location /khdx>
WSGIProcessGroup khdx_wsgi
</Location>

WSGIDaemonProcess sauron_wsgi user=galdosd group=galdosd maximum-requests=10000
WSGIScriptAlias /sauron /home/galdosd/finalsauronweb/django-root/apache/django.wsgi
<Location /sauron>
WSGIProcessGroup sauron_wsgi
</Location>

Solution 2

Domingo Ignacio's answer set me on the right track. I'd like to point out an important fact about making it work: The two process groups must be within the same VirtualHost. (This is based on my tests with Ubuntu 12.04.3 LTS, Apache 2.2.22 and a couple of WSGI apps written in Python.)

For example, this did not work for me, resulting in the ability to access app1 but a 404 error for app2:

<VirtualHost *>
        WSGIDaemonProcess app1 user=someuser group=somegroup threads=5
        WSGIScriptAlias /app1 /app1/app1.wsgi

        <Location /app1>
                WSGIProcessGroup app1
        </Location>
</VirtualHost>

<VirtualHost *>
        WSGIDaemonProcess app2 user=someuser group=somegroup threads=5
        WSGIScriptAlias /app2 /app2/app2.wsgi

        <Location /app2>
                WSGIProcessGroup app2
        </Location>
</VirtualHost>

Removing the middle and tags, so as to have a single VirtualHost, solved the problem:

<VirtualHost *>
        WSGIDaemonProcess app1 user=someuser group=somegroup threads=5
        WSGIScriptAlias /app1 /app1/app1.wsgi

        <Location /app1>
                WSGIProcessGroup app1
        </Location>

        WSGIDaemonProcess app2 user=someuser group=somegroup threads=5
        WSGIScriptAlias /app2 /app2/app2.wsgi

        <Location /app2>
                WSGIProcessGroup app2
        </Location>
</VirtualHost>

Solution 3

I've had trouble with this myself. Instead of trying to get the Apache configuration right, I decided instead to use a single WSGIScriptAlias and have WSGI middleware which routed requests to the correct applications. My code is at https://github.com/zhemao/flotilla. I haven't tested it that much, so use it with caution, but I hope it helps.

Share:
25,299

Related videos on Youtube

Gabriel Hurley
Author by

Gabriel Hurley

I'm an engineer and an artist. I build clouds and cloud-native applications. I'm an expert in Python, JavaScript, and mixology. I believe firmly in open source. My bag of tricks also contains film, photography, graphic design, and audio production. I've been the Project Technical Lead for the OpenStack Dashboard project (Horizon) and a Core Committer for Django (Python web framework). I've worked in startups, enterprises and government agencies. I'm interested in building products that will help shape the world and be used by millions of people.

Updated on July 13, 2022

Comments

  • Gabriel Hurley
    Gabriel Hurley almost 2 years

    I'm trying to get two (or more) Django applications set up at subdirectories under the same domain, e.g.:

    http://example.com/site1/
    http://example.com/site2/
    

    I know that normally this works fine by setting up an apache virtualhost like this:

    <VirtualHost *:80>
        ...
        WSGIScriptAlias /site1 /path/to/site1.wsgi
        WSGIScriptAlias /site2 /path/to/site2.wsgi
    </VirtualHost>
    

    Now, I've verified that each site works individually. But when I try to run both side-by-side, apache sends me to whichever site the worker process loaded first. Example:

    1. Restart apache configured to serve 6 threads
    2. Load example.com/site1/, get the correct page
    3. Load example.com/site2/, get the correct page
    4. Repeat 2 and 3 2 more times.
    5. Refresh example.com/site1/ repeatedly, watch it cycle from site to site.

    Effectively, for any given number of worker processes, it cycles through the total number of them sending the request to whichever one it hit first regardless of the WSGIScriptAlias directive. No matter what I do (setting WSGIProcessGroup, daemon mode vs. embedded mode, or directives) it continues to exhibit this behavior.

    If anyone can point out what I'm doing wrong here, that would be phenomenal!

  • Graham Dumpleton
    Graham Dumpleton almost 13 years
    Use of maximum-requests is discouraged for production sites unless you really have a crippling memory leak you can't fix straight away.
  • Graham Dumpleton
    Graham Dumpleton almost 13 years
    You can't do that with two distinct Django sites because of Django's reliance on single DJANGO_SETTINGS_MODULE environment variable, the value which cannot be changed from one request to the next.
  • Gabriel Hurley
    Gabriel Hurley almost 13 years
    Brilliant! The separate process groups defined inside the Location blocks worked. My only regret is that I didn't ask here sooner ;-)
  • Domingo Ignacio
    Domingo Ignacio almost 13 years
    Thanks, Graham! Is that because of the occasional restart delay?
  • Graham Dumpleton
    Graham Dumpleton almost 13 years
    @Domingo. Yes, because of startup cost and the delay it causes on subsequent requests.
  • Graham Dumpleton
    Graham Dumpleton almost 13 years
    @Gabriel. The best place to ask is the actual mod_wsgi mailing list. I don't always read StackOverflow regularly. The use of separate daemon process groups shouldn't strictly be necessary but too busy to investigate original problem right now and on StackOverflow is the worst place to debug such problems anyway, thus why suggest mailing list.
  • Gabriel Hurley
    Gabriel Hurley almost 13 years
    @Graham -- thanks for the advice. I keep an eye on that list, actually, but figured I'd ask here first in case it was something obvious before escalating to there. I agree it shouldn't be required (and hasn't been required on other projects) but thankfully this worked and life can go on until we all have more time! ;-)
  • Timmmm
    Timmmm over 11 years
    Sadly it didn't work for me, possibly because my WSGIScriptAliases are / and /foo. Any way around that?
  • Domingo Ignacio
    Domingo Ignacio over 11 years
    "Don't Do that Then" :-) ... Sounds like you wish Apache would use the /foo handler whenever it... "matches" something, but use the / handler in other cases. That's not how it works. No mechanism for dynamically coming back to Apache and saying "Never mind I can't handle this request after all, let someone else try". The / handler will get everything and /foo will never have a chance. Maybe you can have /foo and /bar and have some redirects within / to /bar or some similar solution. (Note that by doing this, your set of redirects is acting as the explicit definition of the boundaries)
  • LondonAppDev
    LondonAppDev about 10 years
    Any way to get it to work with alias's / and /foo ? It works perfectly with /foo /bar but not with / and /foo...
  • Domingo Ignacio
    Domingo Ignacio almost 10 years
    @MarkWinterbottom - read the comment right above your question ;-) (Timmmm asked the same thing... or I have a time machine)
  • rszalski
    rszalski almost 8 years
    @MarkWinterbottom I know I'm late to the party, but had the same issue. See if this helps: stackoverflow.com/a/23568825/211153
  • edvin
    edvin almost 4 years
    What about If we have two configuration files with one Virtual Host inside of them. Can they work?
  • lukover
    lukover over 3 years
    You need to specifically set the process-group for your Aliases (see docs). Set WSGIScriptAlias /app1 /app1/app1.wsgi process-group=app1 and WSGIScriptAlias / /app2/app2.wsgi process-group=app2, then it should work.
  • Juha Tuomala
    Juha Tuomala over 2 years
    @Timmmm both / and /foo works if you put that "more precise path" first. /foo first and last plain root /. It works like ip-addresses and routing table, more detailed route wins.