用Python编写基于套接字的服务器,推荐的策略?
我最近读了一篇文章,其中列出了一些可以用来实现套接字服务器的策略。即:用Python编写基于套接字的服务器,推荐的策略?,python,sockets,asynchronous,network-programming,c10k,Python,Sockets,Asynchronous,Network Programming,C10k,我最近读了一篇文章,其中列出了一些可以用来实现套接字服务器的策略。即: 使用每个线程为多个客户端提供服务,并使用非阻塞I/O和级别触发就绪通知 使用每个线程为多个客户端提供服务,并使用非阻塞I/O和就绪更改通知 使用每个服务器线程为多个客户端提供服务,并使用异步I/O 为每个服务器线程提供一个客户端,并使用阻塞I/O 将服务器代码构建到内核中 现在,我希望您能给我一个提示,在CPython中应该使用哪个,我们知道它有一些优点,也有一些缺点。我最感兴趣的是高并发下的性能,是的,当前的许多实现都太慢
ForkingMixIn
对其进行基准测试。使用Linux2.6可能会得到一些有趣的结果
另一种方法是使用。那是。但我明白这并不总是可能的 基本上是“1”-它在内部使用select
,只有一个线程处理所有请求。根据文档,它还可以使用轮询
。(编辑:删除了Twisted引用,我认为它使用了asyncore,但我错了)
“2”可能是通过实现的(只需在谷歌上搜索它-以前从未见过它)。
编辑:(来自注释)在Python2.6中,有epoll、kqueue和kevent内置(在支持的平台上)。因此,您不需要任何外部库来执行边缘触发服务
不要排除“4”,因为当线程实际执行或等待IO操作时(可能大多数情况下),GIL将被删除。当然,如果你有大量的联系,这是没有意义的。如果您有很多处理要做,那么python可能对这些方案中的任何一个都没有意义
关于灵活性,请看
实际上,您的问题归结为您将对请求进行多少处理。如果您有大量的处理,并且需要利用多核并行操作,那么您可能需要多个进程。另一方面,如果你只需要监听大量的连接,那么选择或epoll,加上少量的线程就可以了。我喜欢道格拉斯的答案,但作为旁白 您可以使用一个集中式调度线程/进程,该线程/进程使用和委托一组工作线程/来侦听准备就绪通知,以帮助实现并行性目标
然而,正如Douglas所提到的,GIL不会在最长的I/O操作期间保持(因为没有Python API发生任何事情),因此如果您担心的是响应延迟,您可以尝试将代码的关键部分移动到CPython API。我可以建议其他链接吗 是一个跨平台库,用于使用python 2.5中的增强生成器进行面向网络、基于协同路由的编程。在cogen项目的主页上,有几个类似目的的项目的链接。关于“fork”如何?(我假设这就是ForkingMixIn所做的)如果请求是在“无共享”(除DB或文件系统外)体系结构中处理的,那么fork()在大多数*nixes上启动得非常快,您不必担心线程带来的所有愚蠢的错误和复杂性 IMHO说,线程是一种设计疾病,它是由具有过重进程的操作系统强加给我们的。克隆具有“写时复制”属性的页表似乎价格不高,尤其是在运行解释器的情况下 很抱歉,我不能说得更具体了,但我更多的是一个Perl向Ruby程序员的过渡(当我在工作中没有为大量Java而忙碌时)
更新:我终于在我的“空闲时间”里对线程和fork进行了一些计时。请查看: 扩大: 一种解决方案是gevent。maries是greenlet实现的基于libevent的事件轮询和轻量级协作任务切换 您得到的是事件系统的所有性能和可伸缩性,以及优雅而简单的阻塞IO编程模型
(我不知道回答老问题的惯例是什么,但我决定还是加上我的2美分)谢谢,但你有没有对这些问题进行基准测试?他们很慢。如果不是必须的话,我不会发明轮子。我认为epoll在2.6+的标准库中,并且在2.5版本中易于安装。这个包名为select something。抱歉说得不清楚。Twisted也可以使用epoll。事实上,Twisted将所有受支持的事件通知API转换为一个统一的API,并提供给您。因此,如果平台能做的最好的事情就是选择,那么你的应用程序将使用选择。如果它有epoll,则您的应用程序使用epoll。对你来说都是透明的。@new123456,你说得对,没有人指出这一点