Curl不能在Nginx和localhost上从PHP工作


Curl does not work from PHP on Nginx and localhost

当我通过SSL从本地PHP脚本发送Curl请求到本地服务器(通过WPN-XM在Windows上运行nginx 1.9.4)时,浏览器正在"等待",直到它得到504错误。PHP-fpm可能已经死了,因为web服务器没有处理任何其他请求。

当我向生产服务器发送相同的请求时,它会正常工作。

当我从命令行发送Curl请求时,它就工作了。

当我在web浏览器中打开最终资源时,它就工作了。

我花了4个小时在谷歌上搜索和阅读Stac Owerflow,但没有发现任何像我这样的情况。

谢谢!


<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://webserver.local/resource");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // just on local
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // just on local
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
$response = curl_exec($ch);

这个脚本不能在WPN-XM v0.8.6的默认配置下工作,因为只有一个php-cgi进程在后台监听,但是您的示例需要(至少)两个。php-cgi已经被做curl请求的脚本使用,因此Nginx无法将其转发给php-cgi。这意味着你将首先进入一个带有加载指示符的空白页面,然后达到连接超时。

潜在的问题是php-cgi不能自动生成新进程(当需要时)。这个问题在这里讨论:https://github.com/WPN-XM/WPN-XM/issues/323

有两个解决方案:

  • 使用一个工具来生成服务器,比如
    • https://github.com/WPN-XM/php-cgi-spawner/releases
    • spawn-fcgi从http://www.lighttpd.net/项目启动php-cgi
  • 或启动更多php-cgi进程并配置nginx负载均衡/上游池

Update 03-2016:

为了解决WPN-XM堆栈的情况,我默认添加了php-cgi-spawn'spawn.exe。这允许生成多个PHP守护进程。生成器将用于v7.1以下的PHP版本。

PHP v7.1将实现此解决方案并提供更好的FCGI多路复用开箱即用的。


spawn-fcgi

第一个解决方案是修改start.bat。您只需将spawn-fcgi放在php-cgi前面,如下所示:

spawn-fcgi -f "%_dir%'php-cgi.exe" -a 127.0.0.1 -p 9100 -C 6 -F 4 -P "%_dir%..'temp'php.pid"

我不知道这个工具隐藏在哪里,也许在某个地方有一个独立的下载,但它可能是windows lighttpd发行版的一部分。我想我会从源代码编译它,并使其可用于WPN-XM。

php上游池

第二个解决方案需要两个小步骤来启动并运行PHP工作线程池。

  • 第一步是修改start.bat文件以启动多个php-cgi守护进程,每个守护进程监听不同的端口。我们添加了更多的php-cgi启动:

    :start-php
        echo Starting PHP FastCGI...
        set PHP_FCGI_MAX_REQUESTS=0
        set PHP_FCGI_CHILDREN=4
        %HIDECONSOLE% %~dp0bin'php'php-cgi.exe -b 127.0.0.1:9100 -c %~dp0bin'php'php.ini
        %HIDECONSOLE% %~dp0bin'php'php-cgi.exe -b 127.0.0.1:9101 -c %~dp0bin'php'php.ini
        %HIDECONSOLE% %~dp0bin'php'php-cgi.exe -b 127.0.0.1:9102 -c %~dp0bin'php'php.ini
        %HIDECONSOLE% %~dp0bin'php'php-cgi.exe -b 127.0.0.1:9103 -c %~dp0bin'php'php.ini
    
  • 下一步是修改server'bin'nginx'conf'nginx.conf并激活php_pool,而不是使用单个上游。

    只需查找fastcgi_pass php;并将其更改为fastcgi_pass php_pool;

此更改将激活以下已定义的上游池:

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

运行start.bat,然后你的"curl post to localhost"的例子应该可以工作了