Сочетание трио и колбы

Я пытаюсь создать HTTP API, который может создавать и уничтожать параллельные задачи, которые открывают TCP-соединения с удаленными серверами, передающими потоковые данные ~15 секунд. Я должен выяснить, как обрабатывать данные позже. Сейчас я просто распечатываю это.

В приведенном ниже примере я могу создать несколько соединений TCP, перейдя по http://192.168.1.1:5000/addconnection.

Вопросы:

1) Является ли этот подход разумным? Я думаю, что Flask может создавать новый поток для каждого запроса / addconnection. Я не уверен, какие ограничения производительности я достигну, делая это.

2) Можно ли отслеживать каждое соединение? Я хотел бы реализовать /listconnections и / removeconnections.

3) Есть ли более Pythonic способ сделать это? Я немного читал о сельдерее, но пока не очень хорошо понимаю. Возможно, есть другие уже существующие инструменты для решения подобных проблем.

import trio
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"


@app.route("/addconnection")
def addconnection():

    async def receiver(client_stream):
        print("Receiver: started!")
        while True:
            data = await client_stream.receive_some(16800)
            print("Received Data: {}".format(data))

    async def parent():
        async with trio.open_nursery() as nursery:
            client_stream = await trio.open_tcp_stream('192.168.1.1', 1234)
            nursery.start_soon(receiver, client_stream)

    trio.run(parent)

2 ответа

Решение

1) Вы создадите новый цикл обработки событий для каждого запроса /addconnection, который заблокирует время выполнения Flask. Это, вероятно, ограничит вас одним запросом на поток.

2) Да, в простейшем случае вы можете хранить их в глобальном наборе, см. connections ниже.

3) Я автор Quart-Trio, который я считаю лучшим способом. Quart - это Flask API, заново реализованный с помощью async/await (который решает большую часть из 1)). Quart-Trio - это расширение для использования Trio, а не asyncio для Quart.

Примерно (и я не проверял это) ваш код становится,

import trio
from quart_trio import QuartTrio

connections = set()

app = QuartTrio(__name__)

@app.route("/")
async def hello():
    return "Hello World!"


@app.route("/addconnection")
async def addconnection():

    async def receiver(client_stream):
        print("Receiver: started!")
        while True:
            data = await client_stream.receive_some(16800)
            print("Received Data: {}".format(data))

    async def parent():
        async with trio.open_nursery() as nursery:
            client_stream = await trio.open_tcp_stream('192.168.1.1', 1234)
            connections.add(client_stream)
            nursery.start_soon(receiver, client_stream)
        connections.remove(client_stream)

    app.nursery.start_soon(parent)
    return "Connection Created"

if __name__ == "__main__":
    # Allows this to run and serve via python script.py
    # For production use `hypercorn -k trio script:app`
    app.run()

Вы можете протестировать свой сервер на pythonanywhere.com. Просто предложение.

Другие вопросы по тегам