45

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!

Gabriel Hurley
  • 39,690
  • 13
  • 62
  • 88
  • What do you get when you replace the WSGI script files with that described in 'http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Sub_Interpreter_Being_Used'? – Graham Dumpleton Jul 06 '11 at 05:21

4 Answers4

58

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>
Graham Dumpleton
  • 57,726
  • 6
  • 119
  • 134
Domingo Ignacio
  • 1,194
  • 7
  • 13
  • 3
    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 Jul 06 '11 at 05:18
  • 1
    Brilliant! The separate process groups defined inside the Location blocks worked. My only regret is that I didn't ask here sooner ;-) – Gabriel Hurley Jul 06 '11 at 18:25
  • Thanks, Graham! Is that because of the occasional restart delay? – Domingo Ignacio Jul 06 '11 at 18:31
  • @Domingo. Yes, because of startup cost and the delay it causes on subsequent requests. – Graham Dumpleton Jul 06 '11 at 18:45
  • @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. – Graham Dumpleton Jul 06 '11 at 18:47
  • @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! ;-) – Gabriel Hurley Jul 06 '11 at 21:28
  • 3
    Sadly it didn't work for me, possibly because my `WSGIScriptAlias`es are `/` and `/foo`. Any way around that? – Timmmm Nov 07 '12 at 10:33
  • 2
    "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) – Domingo Ignacio Nov 10 '12 at 23:53
  • Any way to get it to work with alias's / and /foo ? It works perfectly with /foo /bar but not with / and /foo... – LondonAppDev May 01 '14 at 08:33
  • @MarkWinterbottom - read the comment right above your question ;-) (Timmmm asked the same thing... or I have a time machine) – Domingo Ignacio Jul 11 '14 at 20:41
  • 1
    @MarkWinterbottom I know I'm late to the party, but had the same issue. See if this helps: http://stackoverflow.com/a/23568825/211153 – rszalski Sep 15 '16 at 09:41
  • @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. – Juha Tuomala Nov 03 '21 at 16:06
15

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>
Steve Saporta
  • 4,581
  • 3
  • 30
  • 32
  • What about If we have two configuration files with one Virtual Host inside of them. Can they work? –  Aug 12 '20 at 13:03
1

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.

Zhehao Mao
  • 1,789
  • 13
  • 13
  • 1
    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. – Graham Dumpleton Jul 06 '11 at 05:19
0

Anyone know how to get this to work with one of the applications at the root?

This is what I'm currently trying. app2 on the root serves find but I'm getting a 400 bad request: "The browser (or proxy) sent a request that this server could not understand" on app1.

<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.wsgi

    <Location / >
            WSGIProcessGroup app2
    </Location>
Roger Lew
  • 330
  • 3
  • 5
  • You need to specifically set the process-group for your Aliases (see [docs](https://modwsgi.readthedocs.io/en/master/configuration-directives/WSGIScriptAlias.html)). Set `WSGIScriptAlias /app1 /app1/app1.wsgi process-group=app1` and `WSGIScriptAlias / /app2/app2.wsgi process-group=app2`, then it should work. – lukover Feb 09 '21 at 17:16