I have an application using async io to perform parallel requests to different services. It's a flask APP running with Gunicorn.
Unfortunately, some of the requests are kind of long (up to 10s). Until now, I was using the base worker from Gunicorn (sync), but since they are a finited number, I sometime run out of them.
So I've heard about the gevent worker class which for most of the requests allows me to process in parallel, but I don't get how I'm supposed to deal with the code using asyncio. I've reproduced my issue with this simple example :
I use this command to start the server :
gunicorn test_wsgi:app --config=test_wsgi_config.py
With test_wsgi.py:
import asyncio
from flask import Flask
app = Flask(__name__)
async def a_long_task():
await asyncio.sleep(5)
@app.route('/')
def hello():
loop = asyncio.get_event_loop()
loop.run_until_complete(
loop.create_task(a_long_task())
)
return f'Hello, world'
And test_wsgi_config.py
worker_class = "gevent"
When I use worker_class = sync, it works fine, but all the requests are queued. But with gevent, I keep having :
RuntimeError: There is no current event loop in thread 'DummyThread-1'
If I create an event loop :
@app.route('/')
def hello():
asyncio.set_event_loop(asyncio.new_event_loop())
loop = asyncio.get_event_loop()
loop.run_until_complete(
loop.create_task(a_long_task())
)
return f'Hello, world'
I get :
RuntimeError: This event loop is already running
When I do several commands likes this one :
curl 127.0.0.1:8000 &
I'm not sure of how I'm supposed to deal with that.