PHP 中如何处理并发请求(使用线程、线程池或子进程)
Posted
技术标签:
【中文标题】PHP 中如何处理并发请求(使用线程、线程池或子进程)【英文标题】:how are concurrent requests handled in PHP (using - threads, thread pool or child processes) 【发布时间】:2016-02-11 00:24:56 【问题描述】:我了解 php 支持处理多个并发连接,并且可以根据服务器的不同进行配置,如 answer 中所述
服务器如何管理多个连接它是为每个请求分配一个子进程还是使用线程处理还是使用线程池处理?
linked answer 说一个进程是分叉的,然后评论中的作者说线程或进程,如果使用子进程、线程或线程池提供请求,这会让人感到困惑?
【问题讨论】:
[***.com/questions/1623914/… ,我想这就是你要找的东西 【参考方案1】:据我所知,每个网络服务器都有自己的处理多堆同时请求的方式。 通常 Apache2 应该为每个新请求派生一个子进程。但是您可以按照链接的 *** 答案中的说明以某种方式配置此行为。
例如,nginx 在一个线程中获取每个请求(像 Node.js 那样异步处理新连接)或者有时使用缓存(按照配置;Nginx 也可以用作负载平衡器或 HTTP 代理)。这是为您的应用程序选择正确的网络服务器的事情。
Apache2 可能是一个非常好的网络服务器,但是当你想在生产环境中使用它时,你需要更多的负载平衡。但是,当有多个持续时间很短的连接,甚至是根本不改变的文档(或使用缓存)时,它也有很好的能力。
Nginx 非常好,如果你期望有很多持久的连接和某种长的处理时间。那么你就不需要那么多负载平衡了。
希望我能帮到你;)
来源:
https://httpd.apache.org/docs/2.4/mod/worker.html
https://anturis.com/blog/nginx-vs-apache/
我建议你也看看:What is thread safe or non-thread safe in PHP?
【讨论】:
在 FastCGI 的情况下我无法完全理解,因为 FastCGI 作为不同的应用程序进程运行,线程/进程如何管理来处理传入的请求?我的理解是,在 nginx 的情况下,它本身在大多数情况下不会产生新的线程/进程,而是尝试以 Node.js 异步方式处理它,但是,PHP FastCGI 本身将如何处理它 - 线程或将在处理之前的请求之前被阻塞,或者它取决于 PHP 应用程序开发人员或将使用 FastCGI 的预分叉进程池? 正如 Wikipedia 在他们的 FastCGI 站点上指出的那样,FastCGI-Server 已经拥有一个进程池,可以同时处理多个请求。当您启动 FastCGI 服务器时,该池将被初始化。 en.wikipedia.org/wiki/FastCGI 请注意“实施细节”部分。 有一个冲突,“FastCGI 应用程序可以是单线程或多线程的。对于单线程应用程序,Web 服务器维护一个进程池(如果应用程序在本地运行)来处理客户端请求。池的大小是用户可配置的。多线程 FastCGI 应用程序可以接受来自 Web 服务器的多个连接并在单个进程中同时处理它们“fastcgi.com/drupal/node/6?q=node/15 我们如何知道 PHP Fast CGI 二进制文件是如何工作的,我找不到任何相关信息?【参考方案2】:在做了一些研究之后,我得出了以下结论。
重要的是要考虑如何设置 PHP 服务器以便能够深入了解它。要自行设置服务器和 PHP,可能有三种可能性:
1) 使用 PHP 作为模块(对于许多服务器来说,PHP 有一个直接的模块接口(也称为 SAPI))
2) CGI
3) 快速CGI
考虑案例#1 PHP 作为模块,在这种情况下,模块与 Web 服务器本身集成,现在它将球完全放在 Web 服务器上,它如何处理分叉过程、使用线程、线程池等方面的请求.
对于模块,Apache mod_php 似乎很常用,Apache 本身使用进程和线程处理请求,如answer 中提到的两个模型中的@
Prefork MPM 使用多个子进程,每个子进程都有一个线程,并且 每个进程一次处理一个连接。
Worker MPM 使用 多个子进程,每个子进程有许多线程。每个线程处理 一次连接一个。
显然,其他服务器可能会采用其他方法,但我不知道是否相同。
对于#2 和#3,Web 服务器和 PHP 部分在不同的进程中处理,Web 服务器如何处理请求以及应用程序(PHP 部分)如何进一步处理请求各不相同。例如:NGINX 可以使用异步非阻塞 I/O 处理请求,Apache 可以使用线程处理请求,但是,FastCGI 或 CGI 应用程序如何处理请求是一个不同的方面,如下所述。 Web 服务器如何处理请求以及 PHP 部分如何处理这两个方面对于 PHP 服务器的性能都很重要。
考虑到 #2,CGI 协议使 Web 服务器和应用程序 (PHP) 相互独立,CGI 协议要求应用程序和 Web 服务器使用不同的进程来处理,并且该协议不促进同一进程的重用,这在turn 意味着需要一个新进程来处理每个请求。
考虑到#3,FastCGI 协议通过允许进程重用克服了 CGI 的限制。如果您查看IIS FastCGI link FastCGI 解决了 CGI 中固有的性能问题,它提供了一种机制,可以为许多请求一次又一次地重用单个进程。
FastCGI 通过以下方式保持与非线程安全库的兼容性 提供可重用进程池并确保每个进程 一次只处理一个请求。
也就是说,在 FastCGI 的情况下,服务器似乎维护了一个进程池,并且它使用进程池来处理传入的客户端请求,并且由于进程池不需要线程安全检查,因此它提供了良好的性能。
【讨论】:
【参考方案3】:我认为答案取决于 Web 服务器和 cgi 的部署方式。
在我公司,我们使用 Nginx 作为 web 服务器,使用 php-fpm 作为 cgi,所以并发请求被 php-fpm 作为进程处理,而不是线程。
我们配置最大进程数,每个请求由单个php进程处理,如果有更多请求(大于最大进程数)来,他们等待。
所以,我相信PHP本身可以支持所有这些,但是如何使用它,这取决于。
【讨论】:
所以,这是 FastCGI 的情况,PHP-fpm 的请求是使用我的回答中提到的最大进程数的进程池处理的? ye,就我而言,这正是我的意思。但我不确定在其他网络服务器中它们如何使用。 这基本上为我清除了。当我们说“作为进程”时,这是否意味着在管道中,就像链中的数据包一样,先到先得,而延迟时间是你前面那个人的进程延迟时间?例如100 人打 10 个孩子(静态),10 人立即服务,其他 90 人在 cpu 队列中等待,每个人 9 人,等等。对吗? max_request 如何发挥作用?我看它只是为了重生,例如如果设置为说10
,那么该线程在完成其 10 服务后重新生成。我想也许你的意思是“最大进程数”,也许你的意思是孩子【参考方案4】:
PHP 不处理请求。网络服务器会。
对于Apache HTTP Server
,最受欢迎的是“mod_php”。这个模块实际上是 PHP 本身,但被编译为 web 服务器的模块,所以它被直接加载到里面。
由于使用 mod_php,PHP 会直接加载到 Apache 中,如果 Apache 将使用其 Worker MPM(即使用 Threads)处理并发
对于nginx
,PHP 完全位于具有多个 PHP 进程
它有时让您选择使用non-thread safe
或thread safe
PHP。
但是 setlocale() 函数(如果支持)实际上是修改操作系统进程状态,它不是线程安全的。
当您不确定遗留代码如何工作时,您应该记住它。
【讨论】:
以上是关于PHP 中如何处理并发请求(使用线程、线程池或子进程)的主要内容,如果未能解决你的问题,请参考以下文章