nginx+fastcgi php 使用file_get_contents、curl、fopen读取localhost本站点.php异常的情况

原文:http://www.oicto.com/nginx_fastcgi_php_file_get_contents/

参考:http://os.51cto.com/art/201408/449205.htm

这两天一直在搞windows下nginx+fastcgi的file_get_contents请求。我想,很多同学都遇到当file_get_contents请求外网的http/https的php文件时毫无压力,比如echo file_get_contents(‘http://www.baidu.com’),它会显示百度的页面。但当你请求localhost/127.0.0.1本地网络的php服务时却一直是timeout,无论你将请求时间和脚本运行时间多长都无法返回数据,如file_get_contents(‘http://localhost/phpinfo.php’)。然而当你尝试请求html这样的静态文件时却完全没有问题。是什么原因呢?!

首先,我们知道file_get_contents/curl/fopen打开一个基于tcp/ip的http请求时,请求数据发送到nginx,而nginx则委托给php-cgi(fastcgi)处理php文件,一般情况fastcgi处理完一个php请求后会马上释放结束信号,等待下一个处理请求(当然也有程序假死,一直占用资源的情况)。打开nginx.conf,我们看到下面这一行:

1

2

3

4

5

6

location ~ \.php {

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME d:/www/htdocs$fastcgi_script_name;

include fastcgi_params;

}

上面已经清楚地看到,所有使用php结尾的文件都经过fastcgi处理,而在php.ini的配置文件中也有一句:

cgi.force_redirect = 1

表明,所有php程序安全地强制转向交给cgi处理。

但在windows中,本地127.0.0.1:9000怎样与php-cgi联系的呢?!答案是增加一个php-cgi进程,用它来监听127.0.0.1:9000。通过控制器命令:

RunHiddenConsole.exe D:/www/php/php-cgi.exe -b 127.0.0.1:9000 -c C:/WINDOWS/php.ini

我们就可以在启动windows时,开启一个php-cgi.exe进程监听来自127.0.0.1:9000 的请求。在dos命令下打开netstat –a就可以看到本地计算机下的9000端口处于listening状态(也就是空置,如果没有发送任何请求的话)。

好了,该说说在php中使用file_get_contents()、curl()、fopen()函数访问localhost时为什么不能返回结果。我们再来试验在index.php中加入file_get_contents(‘http://127.0.0.1/phpinfo.php’)语句向phpinfo.php发送一个请求,这时浏览器中的状态指示一直在打转,表示它一直在工作中。打开Dos中的netstat命令,可以看到本地的9000端口的状态为:ESTABLISHED,表示该进程在联机处理中。实际上,这里我们已经同时向nginx发送了两个基于http的php请求,一个是解析index.php,而另一个是phpinfo.php,这样矛盾就出来了,因为我们的windows系统只加载了一个php-cgi进程,因此,它无法同时处理php请求,它只能先处理第一个请求(index.php),而index.php却又在等待phpinfo.php处理结果,phpinfo.php没人帮它处理请求,因为它一直在等待index.php释放结束信号,因此,造成了程序的阻塞状态,陷入了死循环。所以我们就看到了浏览器的状态指示一直在打转。Curl()与fopen函数的原因也相同。

找到了原因,我们也就有了解决办法。

一是,向系统增加一个php-cgi进程,当一个php-cig繁忙时,它能够处理其它php请求。这时需给另一个fastcgi进程分配同一ip的不同端口,比如9001。为了解决两个进程的工作分配情况,在nginx中可以通过upstream模块处理它们的工作权重,这也是很多网站实现负载均衡的解决方案:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

upstream bakend {

server 172.0.0.1:9000 weight = 5 max_fails=0 fail_timeout=30s;

server 172.0.0.1:9001 weight = 5 max_fails=0 fail_timeout=30s;

}

location ~ \.php {

fastcgi_pass bakend;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME d:/www/htdocs$fastcgi_script_name;

include fastcgi_params;

}

这样,端口9000与9001均分到了均等的处理机会,当一个进程(sever)繁忙时,由nginx调配另一个进程处理php程序(这里nginx还有其它原理与实现)。

另一个问题是,手动让系统管理多个php-cgi程序比较麻烦,特别是在远程管理的时候尤为不方便,这时可以通过php-fpm或spawn-fcgi来代替,但在windows中并没有php-fpm的二进制编译版本,只能在unix/linux中使用。具体查看各自的手册。

二是,看请求的程序是否一定需要动态解析,如果不是可以转为html或js的格式。如果file_get_contents(‘http://127.0.0.1/a.html’)则不需要通过fastcgi来处理,也就不会出现阻塞的情况。

三是,php的程序取消交由fastcgi,这样则使每个php请求都会自动打开一个php进程,但不好的方面是php-cgi的优势没有了。

时间: 2024-11-05 11:48:54

nginx+fastcgi php 使用file_get_contents、curl、fopen读取localhost本站点.php异常的情况的相关文章

php读取网络文件curl,fsockopen,file_get_contents,file,fopen几种方法

php读取网络文件 curl, fsockopen ,file_get_contents 几个方法的效率对比 最近需要获取别人网站上的音乐数据.用了file_get_contents函数,但是总是会遇到获取失败的问题,尽管按照手册中的 例子设置了超时,可多数时候不会奏效: $config['context'] = stream_context_create(array(‘http’ => array(‘method’ => “GET”,   ’timeout’ => 5//这个超时时间不

Nginx FastCGI的运行原理

一.FastCGI 1.介绍 CGI全称通用网关接口 Commmon Gateway Interface 用于HTTP服务上的程序服务通信交流的一种工具,CGI程序须运行在网络服务器上. 传统CGI接口方式性能较差,由于每次HTTP服务器遇到动态程序需要重启解析器来执行解析,然后结果被返回给HTTP服务器.这在处理高并发时,几乎是不可能的,因此诞生了FastCGI.另外传统的CGI接口方式安全性也很差 一个可伸缩地.高速地在HTTP服务器和动态脚本语言间通信的接口 接口在linux下是socke

【入门篇】Nginx + FastCGI 程序(C/C++) 搭建高性能web service的Demo及部署发布

http://blog.csdn.net/allenlinrui/article/details/19419721 1.介绍 Nginx - 高性能web server,这个不用多说了,大家都知道. FastCGI程序 - 常驻型CGI程序,它是语言无关的.可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能. Nginx要调用FastCGI程序,需要用到FastCGI进程管理程序(因为nginx不能直接执行外部的cgi程序,我们可使用lighttpd中的s

nginx源码分析--请求体的读取(1)

首先请求体的读取已经进入了HTTP请求的11个阶段,针对有些模块需要对请求体做一些处理,那么这个模块就需要在这个阶段注册函数,其中读取请求体的函数ngx_http_read_client_request_body()是存在的,只不过不同的模块可能对请求体做不同的处理,读取请全体的函数是在某个模块的conent_handler函数中包含的,比如比如proxy模块,fastcgi模块,uwsgi模块等这些模块对请求体感兴趣,那么读取请求体的函数在这些模块的content_handler中注册. 上节

nginx fastcgi php-fpm的关系梳理

CGI(Common Gateway Interface)CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上.CGI可以用任何一种语言编写,只要这种语言具有标准输入.输出和环境变量.如php,perl,tcl等. FastCGIFastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fo

Nginx+FastCGI运行原理

转自  http://book.51cto.com/art/201202/314840.htm Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用.FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可以是ip socket).为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件s

十五大原理之一--Nginx FastCGI的运行原理

一.FastCGI 1.介绍 CGI全称通用网关接口 Commmon Gateway Interface 用于HTTP服务上的程序服务通信交流的一种工具,CGI程序须运行在网络服务器上. 传统CGI接口方式性能较差,由于每次HTTP服务器遇到动态程序需要重启解析器来执行解析,然后结果被返回给HTTP服务器.这在处理高并发时,几乎是不可能的,因此诞生了FastCGI.另外传统的CGI接口方式安全性也很差 一个可伸缩地.高速地在HTTP服务器和动态脚本语言间通信的接口 接口在linux下是socke

Nginx + FastCGI 程序(C/C++)搭建高性能web service的demo

http://blog.csdn.net/chdhust/article/details/42645313 Nginx + FastCGI 程序(C/C++)搭建高性能web service的Demo 1.介绍 Nginx - 高性能web server,这个不用多说了,大家都知道. FastCGI程序 - 常驻型CGI程序,它是语言无关的.可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能. Nginx要调用FastCGI程序,需要用到FastCGI进程

转 Nginx+FastCGI到底是谁影响超时时间

需求: 一个php程序要跑一段时间,但是时间不确定. 问题: 当该php程序运行超过一段时间被强制断开连接. PHP本身超时处理 在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效.真正能够控制 PHP 脚本最大执行时: <value name="request_terminate_timeout">0s</value> 就是说如果是使用