I'm trying to use the gaiohttp worker in Gunicorn with a Django app I'm developing with the following command:
gunicorn -k gaiohttp -b localhost:8080 myproject.wsgi
My ultimate goal is to be able to process requests concurrently - i.e. have 1 gunicorn worker process multiple requests concurrently. There are I/O bound operations which makes these requests slow.
I know an event loop is already running when I'm processing a request:
class MyView(View):
def get(self, request):
loop = asyncio.get_event_loop()
loop.is_running() # True
...
Questions:
How can I perform an operation such as yield from asyncio.sleep(10)
within my view code?
class MyView(View):
def get(self, request):
# Raises AssertionError: yield from wasn't used with future
yield from asyncio.sleep(10)
I can add tasks to the event loop, however they don't block while processing the request
@asyncio.coroutine
def simulate_work():
yield from asyncio.sleep(10)
class MyView(View):
def get(self, request):
# This runs simulate_work(), however, it doesn't block
# the response is returned before simulate_work() is finished
loop = asyncio.get_event_loop()
task = loop.create_task(simulate_work())
I try to use futures, but the event loop is already running
@asyncio.coroutine
def simulate_work(future):
yield from asyncio.sleep(10)
future.set_result('Done!')
class MyView(View):
def get(self, request):
future = asyncio.Future()
asyncio.async(simulate_work(future))
loop = asyncio.get_event_loop()
# Raises RuntimeError: Event loop is running.
loop.run_until_complete(future)
print(future.result())
Clearly there's something I'm not understanding about asyncio or gaiohttp.
How can I have asyncio.sleep(10)
block for the current requests, but not block gunicorn from processing other requests?
If each request takes 10 milliseconds, a single worker dishes out 100 RPS. If some requests take 10 milliseconds, others take, say, up to 5 seconds, then you'll need more than one concurrent worker, so the one request that takes 5 seconds does not "hog" all of your serving capability.
Gunicorn relies on the operating system to provide all of the load balancing when handling requests.
Gunicorn is based on the pre-fork worker model. This means that there is a central master process that manages a set of worker processes. The master never knows anything about individual clients. All requests and responses are handled completely by worker processes.
Gunicorn provides a much more configurable and production-tested server. eventlet allows writing asynchronous, coroutine-based code that looks like standard synchronous Python. It uses greenlet to enable task switching without writing async/await or using asyncio . gevent is another library that does the same thing.
Sorry, you cannot call coroutines from your wsgi application -- WSGI is synchronous protocol, as well as frameworks built on top of it (Django, Flask, Pyramid).
I've implemented gaiohttp
worker but it's second class citizen in asyncio world. If you really need asynchronous HTTP server please try aiohttp.web.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With