Gunicorn gevent:线程中没有当前事件循环

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)

我不确定我应该如何处理这个问题。

Pir*_*jas 1

我通过对事件循环的获取方式进行了一些小的更改,成功地使您的示例正常工作:

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)

这是可行的,因为我们得到了一个新的事件循环,它应该始终有效,然后将其设置为当前事件循环。