运行比CPU内核数量更多的PHP-FPM子级有意义吗



假设我有一个4核4线程的CPU,通过设置pm.max_children = 8选项来运行例如8个PHP-FPM工作程序有意义吗?就我而言,具有4个线程的CPU在"0"中最多只能运行4个进程;真实的";平行的如果由于上下文在这8个进程之间切换而导致CPU时间损失,这不会造成开销吗?

相反,Node.js集群模式文档建议运行与内核数量一样多的worker/children。这里不也适用同样的建议吗?

是的,这是有道理的,您可能应该一直这样做,让我解释一下原因。

PHP不使用线程,而是在单个内核上运行。PHP-FPM产生了许多工作者,因此您可以在多个核心上运行流程。

了解操作系统如何使用进程上下文切换来同时处理多个进程是很重要的。如果你只有一个核心,你仍然可以在你的机器上同时运行多个进程,原因是进程上下文切换。这意味着操作系统将使用单核并在进程之间动态切换,根据各种因素一次处理一个进程,例如进程是否在等待一些I/O、进程运行了多长时间、另一个进程是否具有更高的优先级等。重要的部分是进程上下文切换需要一些时间,并且单个核在多个进程之间共享。

如果你有多个核心,进程可以在每个核心上并行执行,但最有可能的是,你的运行进程仍然比核心多,所以进程上下文切换仍然会发生,只是速度较低。

建议将pm.max_children设置为高于CPU核心的值的原因是,在大多数情况下,php进程不会执行密集的CPU任务,而是主要在等待I/O,例如等待SQL结果、等待一些curl响应或磁盘读写响应。这些操作被称为I/O阻塞,通常会占用请求中的大部分时间。通过将pm.max_children设置为比核心更高的值(有时甚至是核心数量的5-10倍),您可以在进程处于阻塞/空闲状态时从操作系统的上下文切换中受益。

有可能有超过20个PHP进程在等待IO。如果你将pm.max_children设置为核心数量,比如说8,核心可能不会做太多工作,大量请求会堆积起来,响应速度会非常慢。

例如,如果您确信您的php进程没有阻塞I/O,并且只执行一些计算,那么您实际上可能会从只设置与核心一样多的pm.max_children中受益更多,原因是进程上下文切换会减慢速度,运行更多进程会消耗更多资源。然而,这种情况是不寻常的,而且很可能您的进程确实存在I/O阻塞和空闲时间。

这里有一篇很好的文章深入介绍了Linux上的进程上下文切换。

swoole PHP扩展中还使用了一种名为协程的东西。Coroutines也使用上下文切换来执行并发,但是这是通过编程实现的,它消耗的资源要少得多,而且比OS上下文切换快得多。如果使用swole,则不需要php-fpm,因为它更快,但它还有其他需要注意的问题。然而,对于swole,建议您设置与核心一样多的工作线程,以避免操作系统上下文切换。您可以进行数千次协同活动,而不会对性能产生太大影响。

Nodejs使用了一个事件循环,类似于swole的协同程序。建议将worker设置为与核心匹配的原因是为了避免操作系统上下文切换,并使用内置上下文切换,因为它更快、更轻。

一般答案是肯定的,因为尽管您不能在并行中运行那么多线程,但您可以同时运行

需要理解的关键是,在大多数实际应用程序中,处理请求所花费的大量时间并不是使用本地CPU,而是等待数据库查询、外部API,甚至磁盘访问。如果每个CPU核心有一个线程,那么CPU就一直处于空闲状态。允许额外的线程,其中一个线程可以使用CPU,而另一个线程则在等待外部数据。

只有当您的应用程序非常不寻常,并且花费100%的时间使用CPU时,每个内核只能使用一个线程才有意义。

这不适用于node.js的原因是,它使用异步代码在单个线程内实现并发:您可以告诉当前线程"开始这样做,在等待结果的同时,继续处理不同的请求";。这在原生PHP中是不可能的;什么都不共享";方法——每个请求都有自己的线程或进程——但也有一些项目,如Swole和Amp,为这种异步方法添加了支持。

最新更新