Django

Code

Ticket #3003 (closed: duplicate)

Opened 2 years ago

Last modified 1 year ago

Support for AJP server in manage.py

Reported by: Henrik Vendelbo <info@fashoncontent.com> Assigned to: adrian
Milestone: Component: django-admin.py
Version: SVN Keywords: ajp
Cc: Triage Stage: Unreviewed
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

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:])

Attachments

Change History

01/18/07 03:34:44 changed by Simon G. <dev@simon.net.nz>

  • keywords set to ajp.
  • status changed from new to closed.
  • has_patch set to 1.
  • resolution set to duplicate.

#3047 does something similar and is more generic.


Add/Change #3003 (Support for AJP server in manage.py)




Change Properties
Action