2015-05-27 8 views
1

У меня есть TCP-сервер, реализованный в Python, с использованием asyncio's create_server.
Я называю сопрограмму start_server с connection_handler_cb.
Теперь мой вопрос заключается в следующем: предположим, что мой connection_handler_cb выглядит
так:asyncio start_server timeout issue

def connection_handler_cb(reader, writer): 
     while True: 
      yield from reader.read() 
      --do some computation-- 

Я знаю, что только yield from сопрограммы выполняются в настоящее время «одновременно» (я знаю, что это на самом деле не одновременно), все «-do some computation--» часть вызывается последовательно и препятствует запуску всего остального в цикле.

Предположим, мы говорим о TCP-сервере с несколькими клиентами, пытающимися отправить. Может ли эта ситуация вызвать таймаут отправки с другой стороны - на стороне клиента?

ответ

1

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

В любом случае, если вы беспокоитесь о тайм-аутах или зависаниях, используйте loop.run_in_executor для выполнения ваших вычислений в фоновом режиме (это предпочтительнее) или в потоке (вероятно, это не очень хороший выбор, поскольку вы выполняете привязку к ЦП вычислений) без блокировки цикла событий:

import asyncio 
    import multiprocessing 
    from concurrent.futures import ProcessPoolExecutor 

    def comp_func(arg1, arg2): 
     # Do computation here 
     return output 

    def connection_handler_cb(reader, writer): 
     while True: 
      yield from reader.read() 
      # Do computation in a background process 
      # This won't block the event loop. 
      output = yield from loop.run_in_executor(None, comp_func, arg1, arg2) # 
    if __name__ == "__main__": 
     executor = 
     loop = asyncio.get_event_loop() 
     loop.set_default_executor(
      ProcessPoolExecutor(multiprocessing.cpu_count())) 
     asyncio.async(asyncio.start_server(connect_handler_cb, ...)) 
     loop.run_forever()