Skip to main content
 首页 » 编程设计

python之预创建多线程 Python 应用程序

2025年05月04日31duanxz

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

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

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

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

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

我已经阅读了 dangers of mixing threads and prefork .我不会在主进程中创建任何线程,因此不会将互斥锁等锁定机制复制到子进程。我不会 fork 我的任何子进程。可以安全地假设我在这个设计的任何阶段都没有遇到麻烦吗? Python 是否缓解了预 fork 和线程的一些问题?

请您参考如下方法:

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