Opened 18 years ago
Closed 18 years ago
#3003 closed enhancement (duplicate)
Support for AJP server in manage.py
Reported by: | Owned by: | Adrian Holovaty | |
---|---|---|---|
Component: | Core (Management commands) | Version: | dev |
Severity: | normal | Keywords: | ajp |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
With the latest Apache HTTPd 2.2 the Ajp 1.3 protocol is supported as part of the new proxy support. This means that multiple backends can be balanced using standard Apache functionality. Flup already supports Ajp, so it should be a very minor task to add the support. I believe I have a working patch. The only thing I haven't looked at is automatic restarting of the Django process like the FastCGI implementation.
for django.core.management
after def runfcgi(args):
def runajp(args):
"Runs this project as an AJP 1.3 application. Requires flup."
from django.conf import settings
from django.utils import translation
# Activate the current language, because it won't get activated later.
try:
translation.activate(settings.LANGUAGE_CODE)
except AttributeError:
pass
from django.core.servers.ajp import runajp
runajp(args)
runajp.args = '[various KEY=val options, use runajp help
for help]'
after 'runfcgi'
'runajp': runajp,
after 'runfcgi' elfi
elif action == 'runajp':
new django.core.servers.ajp
"""
AJP 1.3 server that implements the WSGI protocol.
Uses the flup python package: http://www.saddi.com/software/flup/
This is a adaptation of the flup package to add AJP 1.3 server support
to run Django apps from Web servers that support the AJP 1.3 protocol.
This module can be run standalone or from the django-admin / manage.py
scripts using the "runfcgi" directive.
Run with the extra option "help" for a list of additional options you can
pass to this server.
"""
import sys, os
version = "0.1"
all = runajp
AJP_HELP = r"""runajp:
Run this project as an ajp application. To do this, the
flup package from http://www.saddi.com/software/flup/ is
required.
Usage:
django-admin.py runajp --settings=yourproject.settings [ajp settings]
manage.py runajp [ajp settings]
Optional Ajp13 settings: (setting=value)
host=HOSTNAME hostname to listen on..
port=PORTNUM port to listen on.
socket=FILE UNIX socket to listen on.
method=IMPL prefork or threaded (default prefork)
maxspare=NUMBER max number of spare processes to keep running.
minspare=NUMBER min number of spare processes to prefork.
maxchildren=NUMBER hard limit number of processes in prefork mode.
daemonize=BOOL whether to detach from terminal.
pidfile=FILE write the spawned process-id to this file.
workdir=DIRECTORY change to this directory when daemonizing
Examples:
Run a "standard" ajp process on a file-descriptor
(for webservers which spawn your processes for you)
$ manage.py runajp method=threaded
Run an ajp server on a TCP host/port
$ manage.py runfcgi method=prefork host=127.0.0.1 port=8025
Run a ajp server on a UNIX domain socket (posix platforms only)
$ manage.py runfcgi method=prefork socket=/tmp/ajp.sock
Run a ajp as a daemon and write the spawned PID in a file
$ manage.py runfcgi socket=/tmp/ajp.sock method=prefork \
daemonize=true pidfile=/var/run/django-ajp.pid
"""
AJP_OPTIONS = {
'host': None,
'port': None,
'socket': None,
'method': 'fork',
'daemonize': None,
'workdir': '/',
'pidfile': None,
'maxspare': 5,
'minspare': 2,
'maxchildren': 50,
}
def ajp_help(message=None):
print AJP_HELP
if message:
print message
return False
def runajp(argset=[], kwargs):
options = AJP_OPTIONS.copy()
options.update(kwargs)
for x in argset:
if "=" in x:
k, v = x.split('=', 1)
else:
k, v = x, True
options[k.lower()] = v
if "help" in options:
return ajp_help()
try:
import flup
except ImportError, e:
print >> sys.stderr, "ERROR: %s" % e
print >> sys.stderr, " Unable to load the flup package. In order to run django"
print >> sys.stderr, " as a ajp application, you will need to get flup from"
print >> sys.stderr, " http://www.saddi.com/software/flup/ If you've already"
print >> sys.stderr, " installed flup, then make sure you have it in your PYTHONPATH."
return False
if optionsmethod in ('prefork', 'fork'):
from flup.server.ajp_fork import WSGIServer
wsgi_opts = {
'maxSpare': int(optionsmaxspare),
'minSpare': int(optionsminspare),
'maxChildren': int(optionsmaxchildren),
}
elif optionsmethod in ('thread', 'threaded'):
from flup.server.ajp import WSGIServer
wsgi_opts = {}
else:
return ajp_help("ERROR: Implementation must be one of prefork or thread.")
# Prep up and go
from django.core.handlers.wsgi import WSGIHandler
if optionshost and optionsport and not optionssocket:
wsgi_optsbindAddress = (optionshost, int(optionsport))
elif optionssocket and not optionshost and not optionsport:
wsgi_optsbindAddress = optionssocket
elif not optionssocket and not optionshost and not optionsport:
wsgi_optsbindAddress = None
else:
return ajp_help("Invalid combination of host, port, socket.")
if optionsdaemonize is None:
# Default to daemonizing if we're running on a socket/named pipe.
daemonize = (wsgi_optsbindAddress is not None)
else:
if optionsdaemonize.lower() in ('true', 'yes', 't'):
daemonize = True
elif optionsdaemonize.lower() in ('false', 'no', 'f'):
daemonize = False
else:
return ajp_help("ERROR: Invalid option for daemonize parameter.")
if daemonize:
from django.utils.daemonize import become_daemon
become_daemon(our_home_dir=optionsworkdir)
if optionspidfile:
fp = open(optionspidfile, "w")
fp.write("%d\n" % os.getpid())
fp.close()
WSGIServer(WSGIHandler(), wsgi_opts).run()
if name == 'main':
runajp(sys.argv[1:])
Change History (1)
comment:1 by , 18 years ago
Has patch: | set |
---|---|
Keywords: | ajp added |
Resolution: | → duplicate |
Status: | new → closed |
#3047 does something similar and is more generic.