Windows 上的 Sanic Python,同一端点上的同步行为 - 这是预期的吗?

Posted

技术标签:

【中文标题】Windows 上的 Sanic Python,同一端点上的同步行为 - 这是预期的吗?【英文标题】:Sanic Python on Windows, Synchronous behavior on the same endpoint - Is this expected? 【发布时间】:2020-05-18 08:35:03 【问题描述】:

琐碎的问题,可能被问了几次。 我知道 Sanic 可以在 Windows 上运行(即检测缺少 uvloop,但绝不会减少后备并按下)。

我的问题是,它还会在 Windows 上异步处理请求吗......?答案似乎是肯定的——毕竟它是一个异步框架。

但是,假设我有一个只是休眠的端点,即 asyncio.sleep(10) 并返回。如果我快速连续两次调用此端点 (/) - 第一个响应会在 10 秒内返回,然后才开始处理第二个请求。所以第二个请求在大约 20 秒后返回(同步行为)。

现在,如果我做了同样的事情,即在 2 个独立端点上运行请求,例如(/i 和 /) - 它们都在请求到达后立即开始处理,第一个需要 10 秒才能响应(如预期的那样) ,然后第二个在第一个之后立即返回(异步行为)。

我有点期待请求处理程序的异步任务被转移到事件循环中,因此即使在快速连续两次调用同一端点时也具有相同的异步行为。

我错过了什么吗?

from sanic import Sanic
from sanic.response import json
import asyncio
app = Sanic("X")

@app.route("/")
async def test(request):
    print("request rcvd")
    await asyncio.sleep(10)
    return json("hello": "world")

@app.route("/i")
async def test(request):
    print("request /i rcvd")
    await asyncio.sleep(10)
    return json("hello": "i")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

【问题讨论】:

【参考方案1】:

如果我快速连续两次调用此端点 (/) - 第一个 响应在 10 秒内返回,然后才进行处理 第二次请求开始

我尝试了您的代码,但恐怕无法重现此行为。对我来说,这两个请求都是立即启动的,并且都在 10 秒后返回了结果。

为了更容易验证,我稍微修改了您的代码并添加了客户端脚本:


server.py

from sanic import Sanic
from sanic.response import json
import asyncio
from datetime import datetime


app = Sanic("X")


@app.route("/")
async def test(request):
    print("request rcvd")
    await asyncio.sleep(10)
    return json("/": str(datetime.now()))


@app.route("/i")
async def test(request):
    print("request /i rcvd")
    await asyncio.sleep(10)
    return json("/i": str(datetime.now()))


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)

client.py

import asyncio
import aiohttp
from datetime import datetime


async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()


async def main():
    print(f'Started: datetime.now()')

    results = await asyncio.gather(
        get('http://127.0.0.1:8000/'),
        get('http://127.0.0.1:8000/'),
    )

    print(f'Finished: results')


asyncio.run(main())

结果:

Started: 2020-02-02 16:50:29.087871
Finished: ['"/":"2020-02-02 16:50:41.137824"', '"/":"2020-02-02 16:50:41.137824"']

当我通过浏览器手动检查所有内容时,我也得到了预期的行为(同一端点上的请求并行启动/完成)。

【讨论】:

以上是关于Windows 上的 Sanic Python,同一端点上的同步行为 - 这是预期的吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 Python3.6 Sanic 在 websockets 中检测到“连接丢失”吗?

Web开发Python实现Web服务器(Sanic)

python Sanic服务器

python Sanic请求参数解析器

Python3 Sanic + ssl证书

Sanic教程