РЕШАЕМАЯ: асинхронные веб-узлы во время логики цикла

#python #loops #websocket #async-await

#python #циклы #веб-сокет #асинхронное ожидание

Вопрос:

Новичок в python. Я пытаюсь заставить что-то работать, и я не знаю, правильна ли моя логика.

Итак, у меня есть weksocket (ws), для того, чтобы этот веб-сокет оставался подключенным, требуется каждая минута, когда он получает «ping», я должен ответить «pong:

Итак, я сделал что-то вроде этого:

 async def run():
    prepare_env("test")
    async with websockets.connect(wss_request_url, ssl=True) as ws:
        while True:
            msg = await ws.recv()
            if msg == "ping":
                print("received: ping")
                await send(ws, "pong")
            else:
                response = json.loads(msg)
                if "something" in response:
                     await handle_message(ws, response)
                else:
                     print(f"received:{response}")
asyncio.get_event_loop().run_until_complete(run())
  

На основе «чего-то» в ответе у меня есть в какой-то момент функция (verify_price), которую необходимо проверить в rest API при изменении цены.

 async def verify_price(ws, old_price):
    price_changed = False
    while price_changed is False:
        price = get_new_price()
        if price <> old_price:
            await send(ws, "pricechanged")
            price_changed = True
  

Моя проблема в том, что, пока я нахожусь внутри этого цикла while, ожидая изменения цены, если я получу еще один пинг, он не ответит с помощью pong и отключит мое соединение.

Тай, Дэнни

Комментарии:

1. «пока я нахожусь внутри этого цикла, если я получу еще один пинг, он не ответит с помощью pong» — вам нужно запустить цикл проверки цен в своем собственном потоке. Основной поток должен отвечать за прослушивание сокета и отправку задач рабочим потокам.

2. Даже «ответ с помощью pong» должен быть задачей другого потока. Ваш основной цикл должен помещать рабочие задания только в конец очереди и возвращаться к прослушиванию как можно быстрее, в то время как пул рабочих потоков продолжает выбирать рабочие задания из начала очереди и выполнять их.

3. … и поскольку у вас не может быть неограниченных потоков, но ожидание изменения цены может занять неограниченное время, создание цикла «пока цена не изменилась» приведет к возможности DOS. Если у вас есть 10 рабочих и поступает 10 запросов «проверить цену», ваша служба больше не будет отвечать, потому что все 10 рабочих потоков будут находиться в цикле занятости, ожидая. Поэтому проверки цен должны быть отдельными задачами в основной рабочей очереди. Если цена не изменилась, рабочий поток должен поместить другую задачу «проверить цену» в конец очереди вместо того, чтобы переходить в сам цикл.

4. … и (последнее замечание) поскольку 10 входящих запросов на проверку цен могут быть для одного и того же товара, и вы не хотите, чтобы ваши рабочие потоки впадали в безумие, параллельно проверяя один и тот же товар, вам нужен реестр того, над чем вы работаете, чтобы повторяющиеся запросы не приводили кповторяющаяся проверка, только для дублирования ответов (т. Е.: «Клиент A, B и C запросили X. Давайте сделаем X один раз, и как только X будет выполнено, уведомите A, B и C.» )

5. @user2260630 В качестве альтернативы вы можете поделиться написанным вами кодом для решения вашей проблемы в своем собственном ответе. Отвечая на ваш собственный вопрос, рекомендуется использовать Stack Overflow, вы можете помочь кому-то другому научиться этому.