eladm26
eladm26

Reputation: 563

asyncio start_server timeout issue

I have a TCP server implemented in Python using asyncio's create_server.
I call the coroutine start_server with a connection_handler_cb.
Now my question is this: let's say my connection_handler_cb looks something
like this:

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

I know that only the yield from coroutines are being run "concurrently" (I know it's not really concurrent), all the "--do some computation--" part is being called sequentially and is preventing everything else from running in the loop.

Let's say we are talking about a TCP server with multiple clients trying to send. Can this situation cause send timeout from the other side - the client side?

Upvotes: 1

Views: 982

Answers (1)

dano
dano

Reputation: 94961

If your clients are waiting for a response from the server, and that response isn't sent until the computation is done, then it's possible the clients could eventually timeout, if the computations took long enough. More likely, though, is that the clients will just hang until the computations are done and the event loop gets unblocked.

In any case, if you're worried about timeouts or hangs, use loop.run_in_executor to run your computations in a background process (this is preferable), or thread (probably not a good choice since you're doing CPU-bound computations) without blocking the event loop:

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

Upvotes: 1

Related Questions