swi*_*tch 5 python gunicorn python-asyncio
我有一个使用 async io 对不同服务执行并行请求的应用程序。这是一个用Gunicorn运行的flask APP。
不幸的是,有些请求有点长(长达 10 秒)。到目前为止,我一直在使用 Gunicorn 的基础工作人员(同步),但由于它们的数量有限,我有时会用完它们。
所以我听说过 gevent 工作类,对于大多数请求,它允许我并行处理,但我不明白应该如何使用 asyncio 处理代码。我用这个简单的例子重现了我的问题:
我使用这个命令来启动服务器:
gunicorn test_wsgi:app --config=test_wsgi_config.py
Run Code Online (Sandbox Code Playgroud)
使用 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'
Run Code Online (Sandbox Code Playgroud)
和 test_wsgi_config.py
worker_class = "gevent"
Run Code Online (Sandbox Code Playgroud)
当我使用worker_class =sync时,它工作正常,但所有请求都排队。但有了 gevent,我一直有:
RuntimeError: There is no current event loop in thread 'DummyThread-1'
Run Code Online (Sandbox Code Playgroud)
如果我创建一个事件循环:
@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'
Run Code Online (Sandbox Code Playgroud)
我得到:
RuntimeError: This event loop is already running
Run Code Online (Sandbox Code Playgroud)
当我执行几个像这样的命令时:
curl 127.0.0.1:8000 &
Run Code Online (Sandbox Code Playgroud)
我不确定我应该如何处理这个问题。
我通过对事件循环的获取方式进行了一些小的更改,成功地使您的示例正常工作:
import asyncio
from flask import Flask
app = Flask(__name__)
async def a_long_task():
await asyncio.sleep(5)
@app.route('/')
def hello():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(
loop.create_task(a_long_task())
)
return f'Hello, world'
Run Code Online (Sandbox Code Playgroud)
这是可行的,因为我们得到了一个新的事件循环,它应该始终有效,然后将其设置为当前事件循环。