如何在 Python 中编写基于套接字的服务器的最佳策略?

在 Python 中编写基于套接字的服务器时,有哪些推荐的策略?
在这里插入图片描述

我们参考了 Py 的官方文档,列出了几种实现套接字服务器的策略:

  1. 使用非阻塞 I/O 和边沿触发就绪通知为每个线程提供服务。
  2. 使用非阻塞 I/O 和就绪状态更改通知为每个线程提供服务。
  3. 使用异步 I/O 为每个服务器线程提供服务。
  4. 使用阻塞 I/O 为每个服务器线程提供服务。
  5. 将服务器代码构建到内核中。

考虑到 Python 中 CPython 既有优点也有缺点, 我们对哪种策略应该在 CPython 中使用感兴趣,我们主要关心高并发下的性能,目前的一些实现太慢了。

策略 5 由于我们不会在内核中对任何内容进行任何修改,我们无法使用。

策略 4 看起来因为 GIL,所以不行。当然,你可以在此使用多处理代替线程,并且这样做会带来显著的提升。阻塞 I/O 还具有易于理解的优点。

对策略 1、2、3 我们了解的不多:

  1. 是传统的 select 或 poll,可以与多处理轻松结合。
  2. 是由较新的 epoll 和 kqueue 使用的就绪状态更改通知。
  3. 我们不确定是否对此有任何内核实现具有 Python 包装器。

所以,在 Python 中,我们拥有一些出色的工具,例如 Twisted,你可能它们是一个更好的方法,尽管我们已经对 Twisted 进行了基准测试,但发现它在多处理器机器上太慢了。也许有 4 个带负载均衡器的 Twisteds 可以做到这一点,我们不知道,我们非常欢迎任何建议。

2、解决方案

下面列出了几种可能的解决方案:

  1. asyncore :asyncore 基本上是策略 1,它在内部使用 select,你只需要一个线程来处理所有请求。根据文档,它还可以使用 poll。

  2. python-epoll :策略 2 可以使用 python-epoll 实现。

  3. select 模块 :在 python 2.6 中,select 模块内置了 epoll、kqueue 和 kevent(在支持的平台上)。因此,你不需要任何外部库来进行边沿触发服务。

  4. fork :如果请求以“共享无”(数据库或文件系统之外)的架构处理,则 fork 在大多数 *nixes 上启动非常快,你无需担心来自线程的所有愚蠢错误和复杂性。

  5. gevent :gevent 将基于 libevent 的事件轮询与由 greenlet 实现的轻量级协作任务切换结合在一起。你获得的是事件系统的全部性能和可扩展性,以及阻塞 IO 编程的优雅和简单模型。

  6. cogen :cogen 是一个用于面向网络的、基于协程的编程的跨平台库,它使用 python 2.5 中的增强型生成器。

  7. socketserver.ForkingMixIn :对于多处理器(多核)机器,由于 GIL,你需要每个内核至少一个进程才能进行扩展。由于你指定需要 CPython,你可能尝试使用 ForkingMixIn 对其进行基准测试。使用 Linux 2.6 可能产生一些有趣的结果。另一种方法是使用 Stackless Python,但可能并不总是可行的。

  8. 使用多线程/多进程的集中式调度程序 :可以使用使用 select 侦听就绪状态通知并委托给工作线程/进程池以帮助实现并行目标的集中式调度线程/进程。不过,GIL 不会在大多数冗长的 I/O 操作期间被持有(因为没有 Python-API 相关的事情正在发生),因此,如果你关心响应延迟,你可以尝试将代码的关键部分移至 CPython API。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值