linux-PHP环境安装
什么是FastCGI
快速通用网关接口(Fast Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。
FastCGI致力于减少网页服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的网页请求。
###FastCGI 的优点
FastCGI 的优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求。
nginx+FastCGI运行原理
Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端。这就是Nginx+FastCGI的整个运作过程。
spawn-fcgi和PHP-FPM对比
- ligttpd的spwan-fcgi在高并发访问的时候,会出现内存泄漏甚至自动重启FastCGI的问题。
- PHP-FPM作为PHP的一个补丁,在安装的时候需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀。同时PHP-FPM在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐使用Nginx+PHP/PHP-FPM这个组合对PHP进行解析。
php安装
- 尽量使用PHP和PHP-FPM版本一致,如果版本之间相差太大,可能会出现兼容问题。
- 早期的时候fpm是PHP的一个补丁包,PHP在 5.3.3 之后已经将php-fpm写入php源码核心了。所以已经不需要另外下载了。
安装相关依赖及软件
centos 5 安装包组:Xsoftware Development
centos 6
1 | yum install zlib libxml libjpeg freetype libpng gd curl libiconv zlib-devel libxml2-devel libjpeg-devel freetype-devel libpng-devel gd-devel curl-devel libxslt* -y |
iconv字符编码转换命令
1 | tar zxf libiconv-1.14.tar.gz |
mcrypt 是php里面重要的加密支持扩展库,这里注意的是mcrypt软件依赖libmcrypt和mhash两个库。
libmcrypt依赖库安装
默认路径:/usr/local/lib/
1 | wget http://downloads.sourceforge.net/mcrypt/libmcrypt-2.5.8.tar.gz |
Mhash是基于离散数学原理的不可逆向的php加密方式扩展库,其在默认情况下不开启。mhash的可以用于创建校验数值,消息摘要,消息认证码,以及无需原文的关键信息保存(如密码)等。
默认路径:/usr/local/lib/
1 | wget http://downloads.sourceforge.net/mhash/mhash-0.9.9.9.tar.gz |
默认路径:/usr/local/bin/
1 | wget http://downloads.sourceforge.net/mcrypt/mcrypt-2.6.8.tar.gz |
配置相关连接
1 | rm -f /usr/lib64/libmcrypt.* |
1 | ln -s /application/mysql/lib/libmysqlclient.so.18 /usr/lib64/ |
PHP安装
1 | ./configure \ |
结果:
1 | +--------------------------------------------------------------------+ |
编译和安装
1 | make && make install |
配置文件补充
--enable-fastcgi
:启用对PHP的FastCGI支持。--enable-fpm
:激活对 FastCGI模式的fpm支持。
Linux 可以不装MySQL,如果连软件包都没有,这样情况可以使用:
1 | —with-mysql=mysqlnd |
配置PHP:
解压包中包含两个配置文件:
- php.ini-development :测试环境使用配置文件,相关debug功能都开启了。
- php.ini-production :生产环境使用配置文件,相关debug功能都关闭了。
1 | cp php.ini-production /application/php/lib/php.ini |
PHP配置完毕。
配置PHP及FCGI进程管理
1 | ln -s /application/php5.3.27/ /application/php |
php-fpm.conf
1 | {pid = /app/logs/php-fpm.pid |
mkdir -p /app/logs
启动:
1 | /application/php/sbin/php-fpm -t |
添加开机自启动:
1 | vim /etc/rc.local |
PHP-FPM 配置文件详解
[global]配置
pid string
: PID文件的位置。默认为空。error_log string
: 错误日志的位置。默认:安装路径 #INSTALL_PREFIX#/log/php-fpm.log。log_level string
: 错误级别。可用级别为:alert(必须立即处理),error(错误情况),warning(警告情况),notice(一般重要信息),debug(调试信息)。默认:notice。emergency_restart_threshold int
: 如果子进程在 emergency_restart_interval 设定的时间内收到该参数设定次数的 SIGSEGV 或者 SIGBUS退出信息号,则FPM会重新启动。0 表示“关闭该功能”。默认值:0(关闭)。emergency_restart_interval mixed
: emergency_restart_interval 用于设定平滑重启的间隔时间。这么做有助于解决加速器中共享内存的使用问题。可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:s(秒)。默认值:0(关闭)。process_control_timeout mixed
: 设置子进程接受主进程复用信号的超时时间。可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:s(秒)。默认值:0(关闭)。daemonize boolean
: 设置 FPM 在后台运行。设置“no”将 FPM 保持在前台运行用于调试。默认值:yes。
Pool Definitions 进程池设置
在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。
1 | [www] |
重要的配置参数
listen string
: 设置接受 FastCGI 请求的地址。user string
: FPM 进程运行的Unix用户。必须设置。group string
: FPM 进程运行的 Unix 用户组。如果没有设置,则默认用户的组被使用。pm string
: 设置进程管理器如何管理子进程。可用值:static,ondemand,dynamic。必须设置。request_terminate_timeout mixed
: 设置单个请求的超时中止时间。该选项可能会对 php.ini 设置中的 ‘max_execution_time’ 因为某些特殊原因没有中止运行的脚本有用。设置为 ‘0’ 表示 ‘Off’。可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:s(秒)。默认值:0(关闭)。rlimit_files int
: 设置文件打开描述符的 rlimit 限制。默认值:系统定义值。pm.max_requests int
: 设置每个子进程重生之前服务的请求数。对于可能存在内存泄漏的第三方模块来说是非常有用的。如果设置为 ‘0’ 则一直接受请求,等同于 PHP_FCGI_MAX_REQUESTS 环境变量。默认值:0。listen.allowed_clients string
: 设置允许连接到 FastCGI 的服务器 IPV4 地址。等同于 PHP FastCGI (5.2.2+) 中的 FCGI_WEB_SERVER_ADDRS 环境变量。仅对 TCP 监听起作用。每个地址是用逗号分隔,如果没有设置或者为空,则允许任何服务器请求连接。默认值:any。
详细配置参数
listen string
: 设置接受 FastCGI 请求的地址。可用格式为:’ip:port’,’port’,’/path/to/unix/socket’。每个进程池都需要设置。listen.backlog int
: 设置 listen(2) 的半连接队列长度。“-1”表示无限制。默认值:-1。listen.allowed_clients string
: 设置允许连接到 FastCGI 的服务器 IPV4 地址。等同于 PHP FastCGI (5.2.2+) 中的 FCGI_WEB_SERVER_ADDRS 环境变量。仅对 TCP 监听起作用。每个地址是用逗号分隔,如果没有设置或者为空,则允许任何服务器请求连接。默认值:any。listen.owner string
: 如果使用,表示设置 Unix 套接字的权限。在Linux中,读写权限必须设置,以便用于 WEB 服务器连接。在很多 BSD 派生的系统中可以忽略权限允许自由连接。默认值:运行所使用的用户和组,权限为 0666。listen.group string
: 参见 listen.owner。listen.mode string
: 参见 listen.owner。user string
: FPM 进程运行的Unix用户。必须设置。group string
: FPM 进程运行的 Unix 用户组。如果没有设置,则默认用户的组被使用。pm string
: 设置进程管理器如何管理子进程。可用值:static,ondemand,dynamic。必须设置。
static
: 子进程的数量是固定的(pm.max_children)。ondemand
: 进程在有需求时才产生(当请求时,与 dynamic 相反,pm.start_servers 在服务启动时即启动。dynamic
: 子进程的数量在下面配置的基础上动态设置:pm.max_children,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers。
pm.max_children int
: pm 设置为 static 时表示创建的子进程的数量,pm 设置为 dynamic 时表示最大可创建的子进程的数量。必须设置。该选项设置可以同时提供服务的请求数限制。类似 Apache 的 mpm_prefork 中 MaxClients 的设置和 普通PHP FastCGI中的 PHP_FCGI_CHILDREN 环境变量。pm.start_servers in
: 设置启动时创建的子进程数目。仅在 pm 设置为 dynamic 时使用。默认值:min_spare_servers + (max_spare_servers - min_spare_servers) / 2。pm.min_spare_servers int
: 设置空闲服务进程的最低数目。仅在 pm 设置为 dynamic 时使用。必须设置。pm.max_spare_servers int
: 设置空闲服务进程的最大数目。仅在 pm 设置为 dynamic 时使用。必须设置。pm.max_requests int
: 设置每个子进程重生之前服务的请求数。对于可能存在内存泄漏的第三方模块来说是非常有用的。如果设置为 ‘0’ 则一直接受请求,等同于 PHP_FCGI_MAX_REQUESTS 环境变量。默认值:0。pm.status_path string
: FPM 状态页面的网址。如果没有设置,则无法访问状态页面,默认值:无。ping.path string
: FPM 监控页面的 ping 网址。如果没有设置,则无法访问 ping 页面。该页面用于外部检测 FPM 是否存活并且可以响应请求。请注意必须以斜线开头(/)。ping.response string
: 用于定义 ping 请求的返回响应。返回为 HTTP 200 的 text/plain 格式文本。默认值:pong。request_terminate_timeout mixed
: 设置单个请求的超时中止时间。该选项可能会对 php.ini 设置中的 ‘max_execution_time’ 因为某些特殊原因没有中止运行的脚本有用。设置为 ‘0’ 表示 ‘Off’。可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:s(秒)。默认值:0(关闭)。request_slowlog_timeout mixed
: 当一个请求该设置的超时时间后,就会将对应的 PHP 调用堆栈信息完整写入到慢日志中。设置为 ‘0’ 表示 ‘Off’。可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:s(秒)。默认值:0(关闭)。slowlog string
: 慢请求的记录日志。默认值:#INSTALL_PREFIX#/log/php-fpm.log.slow。rlimit_files int
: 设置文件打开描述符的 rlimit 限制。默认值:系统定义值。rlimit_core int
: 设置核心 rlimit 最大限制值。可用值:’unlimited’,0 或者正整数。默认值:系统定义值。chroot string
: 启动时的 Chroot 目录。所定义的目录需要是绝对路径。如果没有设置,则 chroot 不被使用。chdir string
: 设置启动目录,启动时会自动 Chdir 到该目录。所定义的目录需要是绝对路径。默认值:当前目录,或者根目录(chroot时)。catch_workers_output boolean
: 重定向运行过程中的 stdout 和 stderr 到主要的错误日志文件中。如果没有设置,stdout 和 stderr 将会根据 FastCGI 的规则被重定向到 /dev/null。默认值:无。
管理FastCGI 进程
启动FastCGI进程
方法一:
1 | /data/app/php/bin/php-cgi --fpm |
方法二:
1 | /data/app/php/sbin/php-fpm start |
推荐采用第二种方法启动FastCGI。
php-fpm logrotate
重新启用log文件。
使用信号重启php-fpm
- INT, TERM 立刻终止
- QUIT 平滑终止
- USR1 重新打开日志文件
- USR2 平滑重载所有worker进程并重新载入配置和二进制模块
示例:
php-fpm 关闭:
1 | kill -INT `cat /data/app/php/var/run/php-fpm.pid` |
php-fpm 重启:
1 | kill -USR2 `cat /data/app/php/var/run/php-fpm.pid` |
php与web中间件整合
php与nginx整合
1 | server { |
fastcgi的优化主要集中在nginx的fastcgi.conf配置文件中。
相关内容参考死磕nginx系列–配置文档解读
测试PHP程序是否正常
1 | cat test.php |
测试MYSQL是否正常
1 |
|
报错汇总:
报错一 编译报错
1 | configure: error: Cannot find OpenSSL's <evp.h> |
解决办法
1 | yum yum install openssl openssl-devel |
报错二 make 报错
1 | Generating phar.php |
解决方法:
1 | ln -s /application/php5.3.27 /application/php |
报错三 make 报错
1 | Generating phar.phar |
解决办法:
1 | [root@test2 php-5.3.27]# mkdir -p ext/phar/phar.phar |
报错四 编译报错:
1 | configure: error: Cannot find OpenSSL's <evp.h> |
解决方法:
1 | [root@nfs-client php-5.3.27]# yum install openssl-devel -y |
报错五编译报错:
1 | checking for XSL support... yes |
解决方法:
1 | [root@nfs-client php-5.3.27]# yum install libxslt-devel -y |
报错六 configure 报错:
1 | checking if we should use cURL for url streams... no |
解决办法
1 | ln -s /application/mysql/lib/libmysqlclient.so.18 /usr/lib64/ |
参考文档
搞不清FastCgi与PHP-fpm之间是个什么样的关系
刚开始对这个问题我也挺纠结的,看了《HTTP权威指南》后,感觉清晰了不少。
首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者。
1 | web server(比如说nginx)只是内容的分发者。比如,如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。好了,如果现在请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器。Nginx会传哪些数据给PHP解析器呢?url要有吧,查询字符串也得有吧,POST数据也要有,HTTP header不能少吧,好的,CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。仔细想想,你在PHP代码中使用的用户从哪里来的。 |
好了,CGI是个协议,跟进程什么的没关系。那fastcgi又是什么呢?Fastcgi是用来提高CGI程序性能的。
1 | 提高性能,那么CGI程序的性能问题在哪呢?"PHP解析器会解析php.ini文件,初始化执行环境",就是这里了。标准的CGI对每个请求都会执行这些步骤(不闲累啊!启动进程很累的说!),所以处理每个时间的时间会比较长。这明显不合理嘛!那么Fastcgi是怎么做的呢?首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是fastcgi的对进程的管理。 |
那PHP-FPM又是什么呢?是一个实现了Fastcgi的程序,被PHP官方收了。
1 | 大家都知道,PHP的解释器是php-cgi。php-cgi只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理(皇上,臣妾真的做不到啊!)所以就出现了一些能够调度php-cgi进程的程序,比如说由lighthttpd分离出来的spawn-fcgi。好了PHP-FPM也是这么个东东,在长时间的发展后,逐渐得到了大家的认可(要知道,前几年大家可是抱怨PHP-FPM稳定性太差的),也越来越流行。 |
好了,最后来回来你的问题。 网上有的说,fastcgi是一个协议,php-fpm实现了这个协议
1 | 对。 |
有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的
1 | 对。php-fpm的管理对象是php-cgi。但不能说php-fpm是fastcgi进程的管理器,因为前面说了fastcgi是个协议,似乎没有这么个进程存在,就算存在php-fpm也管理不了他(至少目前是)。 有的说,php-fpm是php内核的一个补丁 |
有的说,修改了php.ini配置文件后,没办法平滑重启,所以就诞生了php-fpm
1 | 是的,修改php.ini之后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就可以歇着了,通过这种机制来平滑过度。 |
还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干吗又弄出个php-fpm
1 | 不对。php-cgi只是解释PHP脚本的程序而已。 |