The following code (taken from here: https://bitbucket.org/denis/gevent/src/6c710e8ae58b/examples/wsgiserver_ssl.py) implements an extremely fast greenlet powered wsgi webserver:
#!/usr/bin/python
"""Secure WSGI server example based on gevent.pywsgi"""
from gevent import pywsgi
def hello_world(env, start_response):
if env['PATH_INFO'] == '/':
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<b>hello world</b>"]
else:
start_response('404 Not Found', [('Content-Type', 'text/html')])
return ['<h1>Not Found</h1>']
print 'Serving on https://127.0.0.1:8443'
server = pywsgi.WSGIServer(('0.0.0.0', 8443), hello_world, keyfile='server.key', certfile='server.crt')
# to start the server asynchronously, call server.start()
# we use blocking serve_forever() here because we have no other jobs
server.serve_forever()
However, this only runs on one core. How would you modify this to take advantage of multiple processes? Not looking for an answer that involves gunicorn, looking for something simpler.
HINT
Here is a code sample using gevent and multiprocessing, but I still can't figure out how to make this work with WSGI (taken from https://gist.github.com/1169975):
import sys
from gevent import server
from gevent.baseserver import _tcp_listener
from gevent.monkey import patch_all; patch_all()
from multiprocessing import Process, current_process, cpu_count
def note(format, *args):
sys.stderr.write('[%s]\t%s\n' % (current_process().name, format%args))
def echo(socket, address):
print 'New connection from %s:%s' % address
fileobj = socket.makefile()
fileobj.write('Welcome to the echo server! Type quit to exit.\r\n')
fileobj.write('In %s\r\n' % current_process().name)
fileobj.flush()
while True:
line = fileobj.readline()
if not line:
print "client disconnected"
break
if line.strip().lower() == 'quit':
print "client quit"
break
fileobj.write(current_process().name + '\t' + line)
fileobj.flush()
print "echoed", repr(line)
listener = _tcp_listener(('127.0.0.1', 8001))
def serve_forever(listener):
note('starting server')
server.StreamServer(listener, echo).serve_forever()
number_of_processes = 5
print 'Starting %s processes' % number_of_processes
for i in range(number_of_processes):
Process(target=serve_forever, args=(listener,)).start()
serve_forever(listener)
So why not to make this in the same way? https://gist.github.com/1217855
import sys
from gevent import server
from gevent.baseserver import _tcp_listener
from gevent import pywsgi
from gevent.monkey import patch_all; patch_all()
from multiprocessing import Process, current_process, cpu_count
def hello_world(env, start_response):
if env['PATH_INFO'] == '/':
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<b>hello world</b>"]
else:
start_response('404 Not Found', [('Content-Type', 'text/html')])
return ['<h1>Not Found</h1>']
listener = _tcp_listener(('127.0.0.1', 8001))
def serve_forever(listener):
pywsgi.WSGIServer(listener, hello_world).serve_forever()
number_of_processes = 5
print 'Starting %s processes' % number_of_processes
for i in range(number_of_processes):
Process(target=serve_forever, args=(listener,)).start()
serve_forever(listener)