预先生成多线程Python应用程序

时间:2014-12-14 13:31:05

标签: python multithreading architecture gevent preforking

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

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

使用gevent进行分叉可能会导致一些问题,并且gipc正好可以解决这些问题 工作线程有时会从各种来源(例如缓存和数据库)中读取,但如果我理解正确,当I / O发生时,GIL将切换到另一个线程。

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

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

我已阅读dangers of mixing threads and prefork。我不打算在主进程中创建任何线程,因此没有锁定机制(如互斥锁)将被复制到子进程。我不会分叉我的任何子进程。假设我在这个设计的任何阶段没有遇到麻烦,这是否安全? Python是否可以减轻preforking和threading的一些问题?

1 个答案:

答案 0 :(得分:1)

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