mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Got the Sync and Eventlet workers running.
This commit is contained in:
parent
4fe8608196
commit
0c935d06c7
@ -50,32 +50,26 @@ class Arbiter(object):
|
||||
def __init__(self, cfg, app):
|
||||
self.cfg = cfg
|
||||
self.app = app
|
||||
|
||||
|
||||
self.log = logging.getLogger(__name__)
|
||||
|
||||
self.address = cfg.address
|
||||
self.num_workers = cfg.num_workers
|
||||
self.num_workers = cfg.workers
|
||||
self.debug = cfg.debug
|
||||
self.timeout = cfg.timeout
|
||||
self.proc_name = cfg.proc_name
|
||||
self.worker_class = cfg.worker_class
|
||||
|
||||
self.address = address
|
||||
self.num_workers = num_workers
|
||||
self.app = app
|
||||
|
||||
try:
|
||||
self.worker_class = cfg.worker_class
|
||||
except ImportError, e:
|
||||
self.log.error("%s" % e)
|
||||
sys.exit(1)
|
||||
|
||||
self._pidfile = None
|
||||
self.worker_age = 0
|
||||
self.reexec_pid = 0
|
||||
self.master_name = "Master"
|
||||
|
||||
self.opts = kwargs
|
||||
self.debug = kwargs.get("debug", False)
|
||||
self.conf = kwargs.get("config", {})
|
||||
self.timeout = self.conf['timeout']
|
||||
self.proc_name = self.conf['proc_name']
|
||||
self.worker_class = kwargs.get("workerclass", SyncWorker)
|
||||
|
||||
self.log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# get current path, try to use PWD env first
|
||||
try:
|
||||
a = os.stat(os.environ('PWD'))
|
||||
@ -100,8 +94,8 @@ class Arbiter(object):
|
||||
"""
|
||||
self.pid = os.getpid()
|
||||
self.init_signals()
|
||||
self.LISTENER = create_socket(self.conf)
|
||||
self.pidfile = self.opts.get("pidfile")
|
||||
self.LISTENER = create_socket(self.cfg)
|
||||
self.pidfile = self.cfg.pidfile
|
||||
self.log.info("Arbiter booted")
|
||||
self.log.info("Listening at: %s" % self.LISTENER)
|
||||
|
||||
@ -305,7 +299,7 @@ class Arbiter(object):
|
||||
|
||||
os.environ['GUNICORN_FD'] = str(self.LISTENER.fileno())
|
||||
os.chdir(self.START_CTX['cwd'])
|
||||
self.conf.before_exec(self)
|
||||
self.cfg.before_exec(self)
|
||||
os.execlp(self.START_CTX[0], *self.START_CTX['argv'])
|
||||
|
||||
def murder_workers(self):
|
||||
@ -369,8 +363,8 @@ class Arbiter(object):
|
||||
for i in range(self.num_workers - len(self.WORKERS.keys())):
|
||||
self.worker_age += 1
|
||||
worker = self.worker_class(self.worker_age, self.pid, self.LISTENER,
|
||||
self.app, self.timeout/2.0, self.conf)
|
||||
self.conf.before_fork(self, worker)
|
||||
self.app, self.timeout/2.0, self.cfg)
|
||||
self.cfg.before_fork(self, worker)
|
||||
pid = os.fork()
|
||||
if pid != 0:
|
||||
self.WORKERS[pid] = worker
|
||||
@ -382,8 +376,8 @@ class Arbiter(object):
|
||||
util._setproctitle("worker [%s]" % self.proc_name)
|
||||
self.log.debug("Booting worker: %s (age: %s)" % (
|
||||
worker_pid, self.worker_age))
|
||||
self.conf.after_fork(self, worker)
|
||||
worker.run()
|
||||
self.cfg.after_fork(self, worker)
|
||||
worker.init_process()
|
||||
sys.exit(0)
|
||||
except SystemExit:
|
||||
raise
|
||||
|
||||
@ -4,7 +4,15 @@
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from gunicorn.http.parser import Parser
|
||||
from gunicorn.http.request import Request, RequestError
|
||||
from gunicorn.http.response import Response
|
||||
from gunicorn.http.request import Request, KeepAliveRequest, RequestError
|
||||
from gunicorn.http.response import Response, KeepAliveResponse
|
||||
|
||||
__all__ = [Parser, Request, RequestError, Response]
|
||||
__all__ = [
|
||||
Parser,
|
||||
Request,
|
||||
KeepAliveRequest,
|
||||
RequestError,
|
||||
Response,
|
||||
KeepAliveResponse
|
||||
]
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import errno
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
@ -171,13 +172,13 @@ class Request(object):
|
||||
self.response = self.RESPONSE_CLASS(self, status, headers)
|
||||
return self.response.write
|
||||
|
||||
class KeepaliveRequest(http.Request):
|
||||
class KeepAliveRequest(Request):
|
||||
|
||||
RESPONSE_CLASS = KeepAliveResponse
|
||||
|
||||
def read(self):
|
||||
try:
|
||||
return super(KeepaliveRequest, self).read()
|
||||
return super(KeepAliveRequest, self).read()
|
||||
except socket.error, e:
|
||||
if e[0] == errno.ECONNRESET:
|
||||
return
|
||||
|
||||
@ -58,7 +58,7 @@ class Response(object):
|
||||
if self.chunked:
|
||||
write_chunk(self.socket, "")
|
||||
|
||||
class KeepaliveResponse(Response):
|
||||
class KeepAliveResponse(Response):
|
||||
|
||||
def default_headers(self):
|
||||
connection = "keep-alive"
|
||||
|
||||
@ -33,7 +33,7 @@ def options():
|
||||
help='Adress to listen on. Ex. 127.0.0.1:8000 or unix:/tmp/gunicorn.sock'),
|
||||
op.make_option('-w', '--workers', dest='workers',
|
||||
help='Number of workers to spawn. [1]'),
|
||||
op.make_option('-k', '--worker-class', dest='klass',
|
||||
op.make_option('-k', '--worker-class', dest='workerclass',
|
||||
help="The type of request processing to use "+
|
||||
"[egg:gunicorn#main]"),
|
||||
op.make_option('-p','--pid', dest='pidfile',
|
||||
@ -79,44 +79,6 @@ def main(usage, get_app):
|
||||
|
||||
Arbiter(cfg, app).run()
|
||||
|
||||
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
"""\
|
||||
A paster server.
|
||||
|
||||
Then entry point in your paster ini file should looks like this:
|
||||
|
||||
[server:main]
|
||||
use = egg:gunicorn#main
|
||||
host = 127.0.0.1
|
||||
port = 5000
|
||||
|
||||
"""
|
||||
opts = kwargs.copy()
|
||||
if port and not host.startswith("unix:"):
|
||||
bind = "%s:%s" % (host, port)
|
||||
else:
|
||||
bind = host
|
||||
opts['bind'] = bind
|
||||
|
||||
if gcfg:
|
||||
for key, value in list(gcfg.items()):
|
||||
if value and value is not None:
|
||||
if key == "debug":
|
||||
value = (value == "true")
|
||||
opts[key] = value
|
||||
opts['default_proc_name'] = opts['__file__']
|
||||
|
||||
cfg = Config(opts)
|
||||
if cfg.spew:
|
||||
spew()
|
||||
if cfg.daemon:
|
||||
daemonize()
|
||||
else:
|
||||
os.setpgrp()
|
||||
configure_logging(cfg)
|
||||
|
||||
Arbiter(cfg, app).run()
|
||||
|
||||
def run():
|
||||
"""\
|
||||
The ``gunicorn`` command line runner for launcing Gunicorn with
|
||||
@ -239,6 +201,44 @@ def run_paster():
|
||||
|
||||
main("%prog [OPTIONS] pasteconfig.ini", get_app)
|
||||
|
||||
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
"""\
|
||||
A paster server.
|
||||
|
||||
Then entry point in your paster ini file should looks like this:
|
||||
|
||||
[server:main]
|
||||
use = egg:gunicorn#main
|
||||
host = 127.0.0.1
|
||||
port = 5000
|
||||
|
||||
"""
|
||||
opts = kwargs.copy()
|
||||
if port and not host.startswith("unix:"):
|
||||
bind = "%s:%s" % (host, port)
|
||||
else:
|
||||
bind = host
|
||||
opts['bind'] = bind
|
||||
|
||||
if gcfg:
|
||||
for key, value in list(gcfg.items()):
|
||||
if value and value is not None:
|
||||
if key == "debug":
|
||||
value = (value == "true")
|
||||
opts[key] = value
|
||||
opts['default_proc_name'] = opts['__file__']
|
||||
|
||||
cfg = Config(opts)
|
||||
if cfg.spew:
|
||||
spew()
|
||||
if cfg.daemon:
|
||||
daemonize()
|
||||
else:
|
||||
os.setpgrp()
|
||||
configure_logging(cfg)
|
||||
|
||||
Arbiter(cfg, app).run()
|
||||
|
||||
def daemonize():
|
||||
"""\
|
||||
Standard daemonization of a process. Code is basd on the
|
||||
|
||||
@ -51,9 +51,9 @@ def load_worker_class(uri):
|
||||
dist, name = entry_str.rsplit("#",1)
|
||||
except ValueError:
|
||||
dist = entry_str
|
||||
name = "main"
|
||||
name = "sync"
|
||||
|
||||
return pkg_resources.load_entry_point(dist, "gunicorn.arbiter", name)
|
||||
return pkg_resources.load_entry_point(dist, "gunicorn.workers", name)
|
||||
else:
|
||||
components = uri.split('.')
|
||||
if len(components) == 1:
|
||||
|
||||
@ -20,7 +20,7 @@ class AsyncWorker(Worker):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Worker.__init__(self, *args, **kwargs)
|
||||
self.worker_connections = self.conf.worker_connections
|
||||
self.worker_connections = self.cfg.worker_connections
|
||||
|
||||
def handle(self, client, addr):
|
||||
try:
|
||||
@ -46,7 +46,7 @@ class AsyncWorker(Worker):
|
||||
util.close(client)
|
||||
|
||||
def handle_request(self, client, addr):
|
||||
req = KeepaliveRequest(client, addr, self.address, self.conf)
|
||||
req = http.KeepAliveRequest(client, addr, self.address, self.cfg)
|
||||
try:
|
||||
environ = req.read()
|
||||
if not environ or not req.parser.headers:
|
||||
|
||||
@ -4,15 +4,11 @@
|
||||
# See the NOTICE for more information.
|
||||
|
||||
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import select
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
from gunicorn import util
|
||||
|
||||
@ -25,7 +21,7 @@ class Worker(object):
|
||||
|
||||
PIPE = []
|
||||
|
||||
def __init__(self, age, ppid, socket, app, timeout, conf):
|
||||
def __init__(self, age, ppid, socket, app, timeout, cfg):
|
||||
"""\
|
||||
This is called pre-fork so it shouldn't do anything to the
|
||||
current process. If there's a need to make process wide
|
||||
@ -36,17 +32,17 @@ class Worker(object):
|
||||
self.socket = socket
|
||||
self.app = app
|
||||
self.timeout = timeout
|
||||
self.conf = conf
|
||||
self.cfg = cfg
|
||||
|
||||
self.nr = 0
|
||||
self.alive = True
|
||||
self.spinner = 0
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.debug = conf.get('debug', False)
|
||||
self.debug = cfg.debug
|
||||
self.address = self.socket.getsockname()
|
||||
|
||||
self.fd, self.tmpname = tempfile.mkstemp(prefix="wgunicorn-")
|
||||
util.chown(self.tmpname, conf.uid, conf.gid)
|
||||
util.chown(self.tmpname, cfg.uid, cfg.gid)
|
||||
self.tmp = os.fdopen(self.fd, "r+b")
|
||||
|
||||
def __str__(self):
|
||||
@ -83,7 +79,7 @@ class Worker(object):
|
||||
super(MyWorkerClass, self).init_process() so that the ``run()``
|
||||
loop is initiated.
|
||||
"""
|
||||
util.set_owner_process(self.conf.uid, self.conf.gid)
|
||||
util.set_owner_process(self.cfg.uid, self.cfg.gid)
|
||||
|
||||
# For waking ourselves up
|
||||
self.PIPE = os.pipe()
|
||||
|
||||
@ -39,7 +39,6 @@ class EventletWorker(AsyncWorker):
|
||||
super(EventletWorker, self).init_process()
|
||||
|
||||
def run(self):
|
||||
self.init_process()
|
||||
self.socket.setblocking(1)
|
||||
|
||||
pool = greenpool.GreenPool(self.worker_connections)
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
|
||||
from gunicorn import http
|
||||
import errno
|
||||
import os
|
||||
import select
|
||||
import socket
|
||||
import traceback
|
||||
|
||||
from gunicorn import http, util
|
||||
from gunicorn.http.tee import UnexpectedEOF
|
||||
from gunicorn.workers.base import Worker
|
||||
|
||||
class SyncWorker(Worker):
|
||||
|
||||
def run(self):
|
||||
self.init_process()
|
||||
self.nr = 0
|
||||
|
||||
# self.socket appears to lose its blocking status after
|
||||
@ -24,7 +29,7 @@ class SyncWorker(Worker):
|
||||
try:
|
||||
client, addr = self.socket.accept()
|
||||
client.setblocking(1)
|
||||
util.close_on_exec(sock)
|
||||
util.close_on_exec(client)
|
||||
self.handle(client, addr)
|
||||
self.nr += 1
|
||||
except socket.error, e:
|
||||
@ -79,7 +84,7 @@ class SyncWorker(Worker):
|
||||
util.close(client)
|
||||
|
||||
def handle_request(self, client, addr):
|
||||
req = http.Request(client, addr, self.address, self.conf)
|
||||
req = http.Request(client, addr, self.address, self.cfg)
|
||||
try:
|
||||
environ = req.read()
|
||||
if not environ or not req.parser.status_line:
|
||||
|
||||
4
setup.py
4
setup.py
@ -48,11 +48,11 @@ setup(
|
||||
gunicorn_django=gunicorn.main:run_django
|
||||
gunicorn_paster=gunicorn.main:run_paster
|
||||
|
||||
[gunicorn.worker]
|
||||
[gunicorn.workers]
|
||||
sync=gunicorn.workers.sync:SyncWorker
|
||||
eventlet=gunicorn.workers.geventlet:EventletWorker
|
||||
gevent=gunicorn.workers.ggevent:GEventWorker
|
||||
|
||||
|
||||
[paste.server_runner]
|
||||
main=gunicorn.main:paste_server
|
||||
""",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user