【问题标题】:Multiple simultaneous requests to PHP script with NGINX使用 NGINX 对 PHP 脚本的多个同时请求
【发布时间】:2018-07-25 08:27:21
【问题描述】:

我有一个运行 NGINX 和 PHP 的网络服务器,带有一个非常基本的多客户端测试。

<?php
    if(isset($_GET['query'])) {
        echo "HELLO MY NAME IS WEBSERVER";
    }
    if(isset($_GET['sleep'])) {
        sleep(10);
    }
?>

如果我运行http://servername.com/index.php?query,我会立即得到响应。

如果我同时运行 ?sleep 然后 ?query,则 ?query 似乎已排队等待 ?sleep 完成。

这发生在多个客户端上。 Client A 可以请求?sleep,这会影响Client B 的?query 请求。客户端 B 是完全不同的机器。

是否有任何方法可以调整 php.ini 或我的 nginx 配置以允许生成单独的 php 工作进程(或类似的东西?)

编辑:对于一点背景,这是我的配置。

nginx.conf:

    location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9123;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
    }

fastgci_params:

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

php执行(runphp.bat):

set PATH=%cd%\php;%PATH%
start %cd%\php\php-cgi.exe -b 127.0.0.1:9123

编辑 2: 好的,看来我需要 PHP-FPM,这在 Windows 上不可用:

It is important to note that FPM is not built with the windows binaries.  Many of the guides you may find online rely on php-cgi.exe.  Unfortunately they call it FPM but this is incorrect!

The executable php-cgi.exe that is bundled with the windows binaries is a FastCGI interface but it is *not* FPM (Fastcgi Process Manager).  php-cgi.exe does not have multi-threading or concurrent request support, nor support for any of the FPM configuration options.

因此,作为一种解决方法,我正在尝试使用多个 php 服务器/进程的方法:

upstream php {
    server  127.0.0.1:9000;
    server  127.0.0.1:9001;
    server  127.0.0.1:9002;
    server  127.0.0.1:9003;
}

location ~ \.php$ {
    fastcgi_pass   php;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

但是,NGINX 在这种配置下根本不会启动。它似乎不想接受任何“上游 php {}”

有什么想法吗?

谢谢

【问题讨论】:

  • PHP到底是如何集成到nginx中的? PHP-FPM?配置了多少个 FPM 工作者?
  • php-fpm的服务器有多少核?创建了多少php-fpm 子进程?您不应该遇到这种行为,我无法在我的设置中复制它。

标签: php nginx


【解决方案1】:

根据编辑,我认为 PHP-FPM 在 Windows 中不可用。 但是,这可以通过在不同端口上生成多个 PHP 进程并配置 NGINX 以在它们之间进行负载平衡来绕过。

我的“RunPHP.bat”脚本:

set PATH=%cd%\php;%PATH%
runhiddenconsole.exe %cd%\php\php-cgi.exe -b 127.0.0.1:9100
runhiddenconsole.exe %cd%\php\php-cgi.exe -b 127.0.0.1:9101
runhiddenconsole.exe %cd%\php\php-cgi.exe -b 127.0.0.1:9102
runhiddenconsole.exe %cd%\php\php-cgi.exe -b 127.0.0.1:9103

我的 nginx.conf(仅限 php 位):

http {

    upstream php_farm {
        server 127.0.0.1:9100 weight=1 max_fails=1 fail_timeout=1s;
        server 127.0.0.1:9101 weight=1 max_fails=1 fail_timeout=1s;
        server 127.0.0.1:9102 weight=1 max_fails=1 fail_timeout=1s;
        server 127.0.0.1:9103 weight=1 max_fails=1 fail_timeout=1s;
    }

    server {
        location ~ \.php$ {
                fastcgi_pass   php_farm;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include        fastcgi_params;

    }

}

【讨论】:

  • 在 Windows 上,您会遇到很多愚蠢的问题,其中之一是流水线处理,即使请求应该是并行的,也会在其中排队。您的问题不包含对 Windows 的任何引用。使用 nginx + php-fpm 运行 Linux VM 将产生预期的结果。使用 Windows 使用 PHP 进行任何类型的适当开发 - 不会。
【解决方案2】:

https://github.com/deemru/php-cgi-spawner

php-cgi-spawner 是最小和最简单的应用程序,可以使用 FastCGI.php-cgi 在 Windows 中为您的 Web 服务器生成多个进程

【讨论】:

  • 这是一个不错的替代解决方案建议,但他的问题是如何让他的 niginx 服务器配置正常工作
【解决方案3】:

您似乎误解了沿 HTTP/Nginx/PHP 的请求流的概念。让我解释一下:

  1. HTTP 是无状态协议。在您的情况下,您需要知道没有机会向客户端发送一些内容,等待一段时间(睡眠),然后再次发送一些内容。
  2. 如果您遇到阻止其他请求的请求的问题,则需要生成更多 PHP-FPM 工作程序来处理许多同时请求。
  3. 有一种方法可以将一些内容发送到客户端、休眠并运行一些其他 PHP 代码。它需要发送一个特殊事件来关闭客户端和服务器之间的连接,但是 PHP 工作者不会完成它的工作。这就是 Symfony 在向客户端发送响应后执行后台任务的方式。

现在你需要调整你的配置。把 Nginx config 的这两个参数带入:

worker_processes  1;
worker_connections  1024;

第一个显示有多少 Nginx worker 正在运行,第二个定义它可以尝试每秒处理多少个连接(基本上)。

之后,请围绕 PHP-FPM 配置进行一些调整。看看这些参数:

pm = dynamic; allows FPM to manipulate number of FPM workers
pm.max_children = 5; defines how many workers run at maximum state
pm.start_servers = 3; defines how many workers run at minimum state
pm.min_spare_servers = 2; defines how many workers run as idle on minimum
pm.max_spare_servers = 4; defines how many workers run as idle on maximum
pm.max_requests = 200; defines how many requests per second should be handled by one worker

基本上这就是你所需要的。现在您必须试验所有这些参数以找到适合您情况的最佳配置。

【讨论】:

  • 你没有正确阅读这个问题,你完全误解了会发生什么。
  • 我已将 worker_processes 设置为 2,并将“PHP-FPM”配置复制并粘贴到我的 php.ini 文件中(我不相信有任何 FPM 配置文件?)问题仍然存在。客户端 A 浏览到 servername.com/index.php?sleep 客户端 B 浏览器到 servername.com/index.php?query 客户端 B 仍然必须等待客户端 A 的 10 秒睡眠完成。客户端 B 似乎在客户端 A 后面排队
猜你喜欢
  • 2016-12-18
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2015-01-27
  • 2020-12-24
  • 2012-05-28
  • 1970-01-01
  • 2017-05-08
相关资源
最近更新 更多