Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asyncio two loops for different I/O tasks?

I am using Python3 Asyncio module to create a load balancing application. I have two heavy IO tasks:

  • A SNMP polling module, which determines the best possible server
  • A "proxy-like" module, which balances the petitions to the selected server.

Both processes are going to run forever, are independent from eachother and should not be blocked by the other one.

I cant use 1 event loop because they would block eachother, is there any way to have 2 event loops or do I have to use multithreading/processing?

I tried using asyncio.new_event_loop() but havent managed to make it work.

like image 816
brunoop Avatar asked Jul 25 '15 05:07

brunoop


People also ask

Does async IO run concurrently?

The intended use of asyncio tasks is to allow independently running tasks to run 'concurrently' with other tasks within the same event loop.

Is async IO multithreaded?

Threading and asyncio both run on a single processor and therefore only run one at a time. They just cleverly find ways to take turns to speed up the overall process. Even though they don't run different trains of thought simultaneously, we still call this concurrency.

How many times should async IO run () be called?

It should be used as a main entry point for asyncio programs, and should ideally only be called once. New in version 3.7.

Is async IO a concurrency?

Asyncio stands for asynchronous input output and refers to a programming paradigm which achieves high concurrency using a single thread or event loop.


2 Answers

The whole point of asyncio is that you can run multiple thousands of I/O-heavy tasks concurrently, so you don't need Threads at all, this is exactly what asyncio is made for. Just run the two coroutines (SNMP and proxy) in the same loop and that's it. You have to make both of them available to the event loop BEFORE calling loop.run_forever(). Something like this:

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

I don't know the structure of your code, so the different modules might have their own infinite loop or something, in this case you can run something like this:

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

Remember, both snmp and proxy needs to be coroutines (async def) written in an asyncio-aware manner. asyncio will not make simple blocking Python functions suddenly "async".

In your specific case, I suspect that you are confused a little bit (no offense!), because well-written async modules will never block each other in the same loop. If this is the case, you don't need asyncio at all and just simply run one of them in a separate Thread without dealing with any asyncio stuff.

like image 104
kissgyorgy Avatar answered Sep 27 '22 17:09

kissgyorgy


Answering my own question to post my solution:

What I ended up doing was creating a thread and a new event loop inside the thread for the polling module, so now every module runs in a different loop. It is not a perfect solution, but it is the only one that made sense to me(I wanted to avoid threads, but since it is only one...). Example:

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 requires that every loop runs its coroutines in the same thread. Using this method you have one event loop foreach thread, and they are totally independent: every loop will execute its coroutines on its own thread, so that is not a problem. As I said, its probably not the best solution, but it worked for me.

like image 26
brunoop Avatar answered Sep 27 '22 15:09

brunoop