Sani c Python на Windows, синхронное поведение на одной и той же конечной точке - ожидается ли это? - PullRequest
2 голосов
/ 02 февраля 2020

Тривиальный вопрос и, вероятно, был задан несколько раз. Я понимаю, что Sani c может работать на Windows (то есть обнаружить отсутствие uvl oop, но, тем не менее, отступить и нажать на).

Мой вопрос: будет ли он по-прежнему обслуживать запросы асинхронно на Windows ....? Ответ, кажется, да - в конце концов, это asyn c framework.

Однако, скажем, у меня есть конечная точка, которая просто спит, т.е. asyncio.sleep (10) и возвращается. Если я вызываю эту конечную точку (/) дважды в быстрой последовательности - первый ответ возвращается через 10 секунд, и только после этого начинается обработка второго запроса. Таким образом, второй запрос возвращается примерно через 20 секунд (синхронное поведение).

Теперь, если я сделал то же самое, то есть запустил запрос на двух независимых конечных точках, скажем (/ i и /) - они оба начинают обработку, как только запрос поступает, первая занимает 10 секунд, прежде чем ответить ( как и ожидалось), а затем второй возвращается сразу после первого (асинхронное поведение).

Я ожидал, что асинхронные задачи обработчика запросов будут отправлены на событие l oop и, следовательно, имеют одинаковое асинхронное поведение c даже при вызове одной и той же конечной точки дважды быстрой последовательности.

Я что-то здесь упускаю?

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 Ответ

0 голосов
/ 02 февраля 2020

Если я вызываю эту конечную точку (/) дважды в быстрой последовательности - первый ответ возвращается через 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"}']

Я также получил ожидаемое поведение (запросы на одну и ту же конечную точку запускаются / заканчиваются параллельно), когда я проверял все вручную через браузер.

...