2

我有一个已经是多线程的 Python 程序,我想用进程替换一些线程,以减少上下文切换并利用 gevent 进行异步 I/O。
主要进程是 I/O 绑定的,所以我想使用 gevent 以便能够处理大量并发 I/O。我们将它称为我系统的接收器组件。

该程序的其余部分主要受 CPU 限制,因此我希望每个进程都有一些线程来处理来自接收器的请求。这些是我的工作进程。
我选择线程在一个进程中处理多个请求的原因是因为线程的创建和销毁成本更低。如果程序收到大量请求,它可以自动扩展以启动更多线程以处理更多请求。当负载减少时,它可以摆脱额外的线程,以避免上下文切换的额外开销。

使用 gevent 分叉可能会导致一些问题,而gipc正是为了解决这些问题而存在的。
工作线程有时会从缓存和数据库等各种来源读取数据,但如果我理解正确,GIL 将在 I/O 发生时切换到另一个线程。

如果我确实决定要在我的工作人员中使用 gevent,我可以(我认为)避免猴子修补线程模块并为每个工作进程分配一个 greenlet 池。当 I/O 发生时,GIL 是否仍会被释放,并且在将 gevent 与线程结合时,另一个线程将开始执行直到 I/O 调用完成?

最后还有另一个过程将响应保存到数据库。它自然是 I/O 绑定的,因此 gevent 将是执行此操作的绝佳选择。

我已经阅读了混合线程和 prefork 的危险。我不会在主进程中创建任何线程,因此不会将诸如互斥锁之类的锁定机制复制到子进程中。我不会分叉我的任何子进程。假设我在这个设计的任何阶段都没有遇到麻烦是否安全?Python 是否减轻了预分叉和线程的一些问题?

4

1 回答 1

1

Python 的 GIL 将阻止单个 Python 进程中的任何实际并发。因此,虽然您可以使用多线程或异步 IO 来处理每个工作人员的大量请求,但要实现真正的并发,您需要 python 的多处理包。您可能应该使用配置了数百个左右请求的 max_requests_per_child 的 Pool,并且必须注意实际进程的数量。如果您的任务在 CPU 上确实很困难,那么如果您没有剩下的内核在做“其他事情”,那么您可以停止系统。但这只能通过实验来推断。

于 2014-12-14T15:48:27.823 回答