Сочетание трио и колбы - PullRequest
1 голос
/ 08 марта 2019

Я пытаюсь создать 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)

1 Ответ

2 голосов
/ 08 марта 2019

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()
...