我需要这个的原因是因为我需要从连接有GPRS调制解调器的1000个设备中轮询数据,并为此设备实现客户端协议实现 有封锁API,例如:
<data> = protocol.get_<some_data>(stream)
所有get方法都是阻塞的:它们只能返回数据或引发异常。 Stream是从GPRS调制解调器到我们的应用程序建立的TCP套接字连接。协议在python中实现。协议复杂性很难描述有大约100种不同类型的设备具有特定功能,并且方法已经意识到这一点,因此协议实现非常复杂,例如将其移植到erlang(我会问这么多钱)我的老板会哭)所以问题听起来像是如何在python中维护1000个线程。我知道这个数量远远超出了python的可能性,不仅仅是因为GIL(我现在使用的是CPython),还因为操作系统会觉得第三次世界大战已经开始(我计划在一台服务器机器上完成所有这些)。 / p>
答案 0 :(得分:1)
假设你绝对必须只使用阻塞I / O(例如,因为你有一个现有的代码库,重写使用非阻塞I / O会太昂贵),最简单的方法是简单地生成1000线程。大多数操作系统可以处理那么多线程(虽然不一定都是有效的),并且GIL不会成为问题,因为等待I / O被阻塞的线程不能保存GIL。 (只有当你试图通过并行化CPU绑定计算来获得加速时才会出现问题;并且听起来你的所有线程都是I / O绑定的)
如果您发现具有1000个线程的进程实际上太多用于您选择的操作系统的线程处理得太可接受,您可以始终将线程分解为多个进程(例如,每个包含100个线程的10个进程,或者其他任何比率你找到最好的作品)。然后,如果问题证明是一个全局线程限制问题(例如,1000个线程太多,无论你将它们分散了多少个进程),那么你接下来要做的就是将它们分散到多台计算机上(例如10个)计算机每个运行100个线程。)
但这些都是丑陋的解决方案;真正的解决方案是重写程序以使用非阻塞I / O,以便每个线程可以同时处理(可能很大)数量的套接字。如果您还没有阅读过,那么您可能需要阅读有关支持许多并发TCP连接的主题的C10K problem文章。