preface
公司所有的大多数业务都泡在LNMP平台上,所以对PHP+Nginx有点了解,那么就做个小小的总结吧。
what's FastCGi
FastCGI是一个可伸缩,高速的在HTTP server和动态脚本语言间通信的接口。FastCGI支持多种脚本语言和HTTP server。
FCGI是由CGI发展改进而来的。传统的CGI接口方式的性能很差。每次HTTP服务器遇到动态程序时都需要重新启动脚本解释器来执行解析,然后将结果返回给HTTP服务器,这在处理高并发访问时几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在很少使用了。
FCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解释器分开,同时在脚本解释器上启动一个或者多个脚本解释器守护进程。当HTTP服务器遇到动态程序时,可以将其直接交付给FCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一的处理静态请求或者动态脚本的结果返回给客户端,这就很大程度上提高了响应速度。
Nginx + FCGI运行原理
Nginx 不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FCGI接口来调用。FCGI接口在linux是socket(这个socket是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FCGI的wrapper(wrapper可以理解为启动另一个程序的程序)。这个wrapper绑定在某个固定的socket上,如端口或者文件的socket,当Nginx将cgi请求发送给这个socket的时候,通过FCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取数据,接着,wrapper将返回的数据通过FCGi接口,沿着固定的socket传给Nginx,最终,NGinx将返回的数据发送给客户端,这就是Nginx+FCGi的运行流程。如图所示:
spawn-fcgi 和 php-fpm
FCGI接口方式在脚本解析服务器上启动一个或者多个守护进程对动态脚本进行解析,这些进程就是FastCGI进程管理器,或者称为fastCgi引擎,spawn-fcgi 和 PHP-FPM就是支持php的两个Fcgi进程管理器。
span-fcgi是HTTP服务器lighttpd的一部分,目前是独立的一个项目,一般与lighttpd配合使用来支持PHP,但是lighttpd的spwan-fcgi在高并发访问的时候,会出现内存泄漏甚至自动重启FastCGI的问题
Nginx是个轻量级的HTTPserver,必须借助第三方的FCGI处理器才可以对PHP进行解析。
PHP-FPM是一个第三方的FCGI进程管理器,它是PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此处理性能方面更加优秀,同事PHP-FPM在处理高并发方面也比spawn-fcgi引擎好很多,所以推荐NGINX+PHP-FPM组合。
FCGI的主要优点是把动态语言和HTTP server分离开来,所以Nginx 与 php、php-fpm经常被部署在不同的服务器上,以分担前端Nginx的服务器压力,让nginx 专一处理静态请求和转发动态请求。而PHP、PHP-fpm服务器专一解析PHP动态请求。
那么就部署它们吧
php下载地址: http://php.net
php-fpm下载地址:http://php-fpm.org/downloads/
我这里下载的php是php-5.5.38
安装之前,把依赖包都安装好,采用yum安装 :
yum -y install gcc gcc++ libxml2 libxml2-devel autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel glibc-devel glib2 glib2-devel
安装好依赖包后,安装php
./configure --prefix=/usr /local/php --enable-fpm --enable-fastcgi(可能会提示没有这个选项)
make && make install
编译没有问题后,我们开始配置和优化php-fpm,php全局配置文件是php.ini,编译后是在/etc/php.ini这下面。
重点介绍php-fpm引擎的配置文件
php-fpm配置文件也在/etc/php-fpm.conf下面,默认情况下会把/etc/php-fpm.d/www.conf 的配置文件include进去。
我们在www.conf里面看看以下几项:
listen = 127.0.0.1:9000 #监听了本地9k端口
user = nginx #运行用户
group = nginx
pm.max_children = 50 # 设置fcgi的进程数,官方建议小于2G内存开启64个,4G可以开200个
request_terminate_timeout = 0 # 用于设置FCGI执行脚本的时间,默认是0秒,也就是五险的执行下去,可以更加情况改
rlimit_files = 1024 #设置PHP-FPM 打开文件描述符的限制,这个值要和linux内核打开文件数关联起来,例如,要将此值设置为65535,就必须在linux命令上执行ulimit -HSN 65536
pm.max_requests = 500 设置处理多少个请求后便会关闭,默认是500,
listen.allowed_clients = 127.0.0.1 # 设置允许访问FCGI进程解析器的IP地址,如果不在IP地址,将无法接受Nginx转发过来的php解析请求。
了解完上诉配置后,就可以启动FastCGI了,启动命令如下:
[root@salt ~]# php-fpm 启动php-fpm
如果有像这样的报错:
[root@salt php]# php-cgi
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/redis.so' - /usr/lib64/php/modules/redis.so: undefined symbol: igbinary_unserialize in Unknown on line 0
那么在/etc/php.ini把这行注释掉启动就可以了:
; extension=/usr/lib64/php/modules/redis.so
Notice
如果是php7.0版本以上的,可以使用以下命令安装redis
[root@salt ~]# pecl install redis
pecl/redis requires PHP (version >= 7.0.0, version <= 7.1.0, excluded versions: 6.0.0), installed version is 5.5.32
No valid packages found
install failed
配置nginx来支持php
我们切换到nginx配置文件目录下,发现有个default.conf的模版文件,我们copy一份来修改后即可用,命令如下:
[root@salt ~]# cd /etc/nginx/conf.d/
[root@salt conf.d]# ls
default.conf
[root@salt conf.d]# cp default.conf web1.conf
[root@salt conf.d]# mv default.conf default.cf # 避免默认配置影响nginx运行
[root@salt conf.d]# vim web1.conf
# 写入以下内容:
server {
listen 80;
server_name web1.test.com;
charset utf8;
location / {
root /var/www/html;
index index.html index.htm;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;;
include fastcgi_params;
}
}
参数解释
- location 正则匹配到以php结尾的到这里解析,
- root 指明了网站目录
- fastcgi_pass 指明了用哪里的php-fpm来解析
- fastcgi_index 指明首页
- fastcgi_param 指明的是php动态程序的主目录,/scripts也就是$fastcgi_script_name前面指定的路径,我们一般在这里写网站根目录的路径,比如我们的路径是 /var/www/html。
测试php+nginx是否正常工作
在网站根目录下面创建Index.php文件,写入一些内容,命令如下:
/var/www/html/index.html的内容:
<h1>
<span> hello, this is test page </span>
</h1>
/var/www/html/phpinfo.php内容:
<?php phpinfo(); ?>
我们访问http://ip/如果出现自定义页面,那么就成功了。
访问http://ip/phpinfo.php 出现php安装信息,那么也算成功了。
优化Nginx和FastCgi参数
我们在nginx配置文件里面的http段内添加一下内容,比如我们现在使用的web1.conf文件,那么我就在web1.conf里面添加以下内容:
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
参数解释
fastcgi_connect_timeout 300;` 值连接到后端FastCGI的超时时间
fastcgi_send_timeout 300; 指向Fastcgi 传送请求的超时时间,这个值是已经完成了2次握手后向FastCGI应答的超时时间
fastcgi_read_timeout 300; 指向接收FastCGI应答的超时时间,这个是已经完成2次握手后接收FastCGI应答的超时时间
fastcgi_buffer_size 64k; 用于指定读取FastCGI。 应答第一部分需要多大的缓冲区,这个值表示将使用1个64KB的缓冲区读取应答的第一部分(应答头),可以设置Fastcgi_buffers选项指定的缓冲区大小。
fastcgi_buffers 4 64k; 指定本地需要多少和多大的缓冲区缓冲FastCGI的应答请求。如果一个PHP脚本所产生的页面大小为256KB,那么就会为其分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到Fastcgi_temp指定的路径中。但是这个不是好办法。因为内存中的数据处理速度大于硬盘,一般这个值应该为站点中的php脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为16 16K,或者4 64KB。。
fastcgi_busy_buffers_size 128k; 默认值是fastcgi_buffers的两 倍
fastcgi_temp_file_write_size 128k; 表示写入缓存文件时使用多大的数据块,默认是fastcgi_buffers的两倍。
开启缓存后:
fastcgi_cache_valid 200 302 1h;将http状态码是200的和302的缓存一小时,301的缓存一天,其他的缓存一分钟fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
写完以上参数后,保存退出重启服务。