一、CGI协议与FastCGI协议
CGI(Common Gateway Interface:通用网关接口
)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。
FastCGI程序和web服务器之间通过可靠的流式传输(Unix Domain Socket或TCP)来通信,相对于传统的CGI程序,有环境变量和标准输入输出,而FastCGI程序和web服务器之间则只有一条socket连接来传输数据
CGI协议是用来使解释器与服务器可以互相通信。PHP文件在服务器上的解析需要用到php解释器,再加上对应的cgi协议,从而使服务器可以解析到PHP文件。而CGI机制是每处理一个请求需要fork一个cgi进程,请求结束再kill掉这个进程,再实际应用上比较浪费资源,于是就出现了cgi的改良版fast成功i,fastcgi在请求处理后,不会kill掉进程,而是继续处理多个请求,这样就大大提高了效率。
二、PHP-FPM是什么?
php-fpm 即 PHP-FastCGI Progress Manager,它是FastCGI的实现,并提供了进程管理的功能。进程包含master进程和worker进程两种;master进程只有一个,负责监听端口,接收来自服务器的请求,而worker进程则一般有多个(具体数量根据实际需要进行配置),每个进程内部都会嵌入一个php解释器,是代码真正执行的地方。
nginx与php-fpm通信机制,处理流程是这样的,当我们访问一个网站(www.test.com)
www.test.com —— nginx ——路由到www.test.com/index.php ——加载nginx的fast-cgi模块 —— fast-cgi监听127.0.0.1:9000地址 —— www.test.com/index.php请求到达127.0.0.1:9000 —— 等待处理.......
三、Nginx与php-fpm的结合
在linux上,nginx与php-fpm的通信有tcp socket 和unix socket两种方式。
tcp socket 又叫IPC(inter-process communication 进程间通信)socket,用于实现同一主机上的进程间通信,这种方式需要在nginx配置文件中填写php-fpm的socket文件位置。
两种方式的数据传输过程如下图所示:
二者的不同:
由于unix socket不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。所以其效率比tcp socket 的方式要高,可减少不必要的tcp开销。不过,unix socket高并发时不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。而tcp这样的面向连接的协议,可以更好的保证通信的正确性和完整性。
Nginx 与 PHP-FPM结合只需要在各自的配置文件中设置即可:
1、Nginx中的配置
以tcp socket通信为例
server{
listen 80; #监听80端口,接收http请求
server_name www.test.com; #就是网站地址
root /var/www/html/test; #准备存放代码工程的路径
#路由到网站根目录 www.test.com 时候的处理
location / {
index index.php; #跳转到www.test.com/index.php
autoindex on;
}
#当请求网站下php文件的时候,反向代理到php-fpm
location ~ \.php$ {
include /usr/local/etc/nginx/fastcgi.conf; #加载nginx的fastcgi模块
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000; #tcp 方式,php-fpm监听的ip地址和端口
#fastcgi_pass /usr/run/php-fpm.sock #unix socket 连接方式
}
}
2、php-fpm配置
listen = 127.0.0.1:9000 # listen = /var/run/php-fpm.sock
在应用中的选择
如果是同一台服务器上运行的nginx和php-fpm,且并发量不高(不超过1000)选择unix socket,以提高nginx和php-fpm的通信效率。
如果是面临高并发业务,则考虑选择使用更可靠的tcp socket,以负载均衡、内核优化等运维手段维持效率。
若并发较高但仍想用unix socket时,可通过以下方式提高unix socket的稳定性。
1) 将sock文件放在/dev/shm目录下,此目录下将sock文件放在内存里面,内存的读写更快。
2) 提高backlog
backlog默认位 128,1024这个值换成自己正常的QPS,配置如下:
nginx.conf文件中
server {
listen 80 default backlog = 1024;
}
php-fpm.conf文件中
listen.backlog = 1024
3) 增加sock文件和php-fpm实例
在/dev/shm新建一个sock文件,在nginx中通过upstream模块将请求负载均衡到两个sock文件,并且将两个sock文件分别对应到两套php-fpm实例上。