Asyncio два цикла для разных задач ввода /вывода?

Я использую модуль Python3 Asyncio для создания приложения балансировки нагрузки. У меня есть две тяжелые задачи ввода-вывода:

  • Модуль опроса SNMP, который определяет наилучший сервер
  • Прокси-подобный модуль, который балансирует петиции на выбранный сервер.

Оба процесса будут работать вечно, не зависят друг от друга и не должны блокироваться другим.

Я не могу использовать 1 цикл обработки событий, потому что они будут блокировать друг друга, есть ли способ иметь 2 цикла обработки событий или мне нужно использовать многопоточность /обработку?

Я пытался использовать asyncio.new_event_loop (), но не смог заставить его работать.

12 голосов | спросил brunoop 25 J000000Saturday15 2015, 08:12:20

5 ответов


0

Отвечая на мой вопрос, чтобы опубликовать свое решение:

Я закончил тем, что создал поток и новый цикл обработки событий внутри потока для модуля опроса, так что теперь каждый модуль работает в отдельном цикле. Это не идеальное решение, но это единственное, что имело смысл для меня (я хотел избежать потоков, но так как это только один ...). Пример:

import asyncio
import threading


def worker():
    second_loop = asyncio.new_event_loop()
    execute_polling_coroutines_forever(second_loop)
    return

threads = []
t = threading.Thread(target=worker)
threads.append(t)
t.start()

loop = asyncio.get_event_loop()
execute_proxy_coroutines_forever(loop)

Asyncio требует, чтобы каждый цикл выполнял свои сопрограммы в одном и том же потоке. Используя этот метод, у вас есть один цикл событий foreach, и они полностью независимы: каждый цикл будет выполнять свои сопрограммы в своем собственном потоке, так что это не проблема. Как я уже сказал, это, вероятно, не лучшее решение, но оно сработало для меня.

ответил brunoop 27 J000000Monday15 2015, 04:31:45
0

Весь смысл asyncio заключается в том, что вы можете одновременно выполнять несколько тысяч задач с интенсивным вводом-выводом, поэтому нужно Thread, это именно то, что asyncio

import asyncio

async def snmp():
    print("Doing the snmp thing")
    await asyncio.sleep(1)

async def proxy():
    print("Doing the proxy thing")
    await asyncio.sleep(2)

async def main():
    while True:
        await snmp()
        await proxy()

loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()

Я не знаю структуру вашего кода, поэтому разные модули могут иметь свой собственный бесконечный цикл или что-то в этом случае, в этом случае вы можете запустить что-то вроде этого:

import asyncio

async def snmp():
    while True:
        print("Doing the snmp thing")
        await asyncio.sleep(1)

async def proxy():
    while True:
        print("Doing the proxy thing")
        await asyncio.sleep(2)

loop = asyncio.get_event_loop()
loop.create_task(snmp())
loop.create_task(proxy())
loop.run_forever()

Помните, что snmp и proxy должны быть сопрограммы (async def), написанные с учетом асинхронности. asyncio не сделает простую блокировку функций Python внезапно "асинхронной".

В вашем конкретном случае я подозреваю, что вы немного смущены (без обид!), потому что хорошо написанные асинхронные модули никогда не будут блокировать друг друга в одном цикле. Если это так, вам не нужно asyncio, а просто запустите один из них в отдельном Thread без каких-либо asyncio вещей.

ответил kissgyorgy 27 +03002018-10-27T20:09:29+03:00312018bEurope/MoscowSat, 27 Oct 2018 20:09:29 +0300 2018, 20:09:29
0

Цикл событий Asyncio - это отдельный поток, и он не будет запускать что-либо параллельно, как он спроектирован. Самое близкое, о чем я могу подумать, это использовать asyncio.wait.

from asyncio import coroutine
import asyncio

@coroutine
def some_work(x, y):
    print("Going to do some heavy work")
    yield from asyncio.sleep(1.0)
    print(x + y)

@coroutine
def some_other_work(x, y):
    print("Going to do some other heavy work")
    yield from asyncio.sleep(3.0)
    print(x * y)



if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([asyncio.async(some_work(3, 4)), 
                            asyncio.async(some_other_work(3, 4))]))
    loop.close()

альтернативный способ - использовать asyncio.gather() - он возвращает будущие результаты из данного списка фьючерсов.

tasks = [asyncio.Task(some_work(3, 4)), asyncio.Task(some_other_work(3, 4))]
loop.run_until_complete(asyncio.gather(*tasks))
ответил Nihal Sharma 25 J000000Saturday15 2015, 12:06:04
0

Но я использовал это вот так, но все равно синхронно, без асинхронности:

def main(*args):    
    loop = get_event_loop()
    coro = asyncio.start_server(handle_echo, '127.0.0.1', 50008,loop=loop)
    srv = loop.run_until_complete(coro)        
    loop.run_forever()    

@asyncio.coroutine
def handle_echo(reader, writer):
    data = yield from reader.read(500)
    message = data.decode(encoding='utf-8')            

    nameindex=('name="calculator2"' in message)
    if nameindex:
        time.sleep(5)
        writer.write("Content-Length: 1\r\n\r\n2".encode())
        yield from writer.drain()
    else:
        writer.write("Content-Length: 1\r\n\r\n1".encode())
        yield from writer.drain()



    print("Close the client socket")
    writer.close()

если полученное значение содержит (name = "calculator2"), я жду 5 секунд если нет, просто ответьте и запишите данные немедленно. Но когда это проверяется, сначала отправьте данные на сервер с содержащими (name = "calculator2") и следующие данные без (name = "calculator2"), но последующие обработчики данных будут выполнены через 5 секунд после первого и после этого будут обработаны 2-ые данные .

его последовательный. что с ним не так? и наоборот, как мне подключить клиентские IP и порт?

ответил Hamed_gibago 7 MarpmTue, 07 Mar 2017 15:15:17 +03002017-03-07T15:15:17+03:0003 2017, 15:15:17
0
  

Если прокси-сервер работает все время, он не может переключаться назад и вперед. Прокси-сервер прослушивает клиентские запросы и делает их асинхронными, но другая задача не может быть выполнена, потому что эта выполняется вечно.

Если прокси-сервер является сопрограммой и не использует SNMP-опросчик (никогда не ждет), разве клиентские запросы также не подвергаются голоданию?

  

каждая сопрограмма будет работать вечно, они не закончатся

Это должно быть хорошо, если они это делают await/yield from. эхо-сервер также будет работать вечно , это не значит, что вы не можете запустить несколько серверов (хотя и на разных портах) в одном цикле.

ответил Markus Bergkvist 9 WedEurope/Moscow2015-12-09T23:32:18+03:00Europe/Moscow12bEurope/MoscowWed, 09 Dec 2015 23:32:18 +0300 2015, 23:32:18

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132