python 3.5 - asyncio - 运行并发连接池

时间:2016-03-26 00:16:26

标签: python multithreading websocket python-asyncio

我主要是一名PHP / Java程序员,而且我对Pythons并发相当新,所以我遇到了这个问题:

我有一个websocket服务器接受asyncio的主事件循环上的连接,从我可以告诉事件循环是单线程的,所以我试图为每个连接的客户端创建一个ThreadPoolExecutor,其中有一个无休止的等待-ed循环侦听来自每个连接的客户端的通信

这是我的代码:

import asyncio
from concurrent.futures import ThreadPoolExecutor

loop = asyncio.get_event_loop()
connected = set()

executor = ThreadPoolExecutor(max_workers=500)

def main():
    import websockets
    from includes.Client import Client

    async def handler(websocket, path):
        global connected
        client = Client(websocket)
        connected.add(client)
        executor.submit(await client.receive_loop())
        print('< client connected')

    server = websockets.serve(handler, 'localhost', 40004)
    loop.run_until_complete(server)
    loop.run_forever()

if __name__ == '__main__' : main()

这是“client.receive_loop()”

async def receive_loop(self):

    try:
        while True:
            message = await self.socket.recv()
            self.process_message(message)
    except websockets.exceptions.ConnectionClosed:
        print('> client disconnected')
        self.socket.close()

我的问题是,不是在线程池上运行“receive_loop”,而是在运行打印“client connected”之前等待客户端断开连接。 奇怪的是,它接受多个连接...

我已经尝试过查看Python,Asyncio和websocket lib的文档,但我还没知道如何做到这一点,我发现python的文档非常混乱(至少与PHP相比)。

任何帮助?

1 个答案:

答案 0 :(得分:2)

在您的示例中,receive_loop不应该是协程,而是一个简单的函数。但总的来说,你想要做的事情并没有多大意义。为每个客户端添加一个线程不会让它变得更好。 Asyncio可以在一个线程中处理所有客户端。另一方面,你只能使用线程而不使用asyncio和协同程序。所以它更像你需要决定 - 你打算在这里使用线程或asyncio。我建议使用asyncio,因为在python线程中由于GIL而没有增加很多价值。另外我建议检查aiohttp库中的asyncio,它有websockets的例子。