目录
FastCGI
PHP-FPM
FPM配置
Nginx配置
FastCGI
FastCGI = Fast + CGI
因此 想要理解FastCGI的关键就在于CGI
CGI = Common Gateway Interface
Common Gateway Interface (CGI) offers a standard protocol for web servers
to execute programs that execute like Console applications (also called Command-line interface programs) running on a server that generates web pages dynamically
上述定义摘自Wiki - Common Gateway Interface
理解了CGI 那么想要理解"Fast"的CGI就很容易了
FastCGI's main aim is to reduce the overhead associated with interfacing the web server and CGI programs
allowing a server to handle more web page requests at once
那么FastCGI时如何做到更优的性能的呢? 答案就是
Instead of creating a new process for each request, FastCGI uses persistent processes to handle a series of requests
上述定义摘自Wiki - FastCGI
PHP-FPM
我们已经知道FastCGI是Web Server和应用程序之间的通信协议
那么无论是Web Server 还是应用程序都需要遵守并实现FastCGI协议
当前主流的Web Server都支持FastCGI
Apache HTTP Server
Lighttpd
Microsoft IIS
Nginx
同时主流的编程语言也都有相应的实现 详细参考Language bindings for the FastCGI API
而已经成为PHP官方标配的最佳实现就是这里的主角: PHP-FPM
PHP-FPM = PHP - FastCGI Process Manager
PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation
with some additional features useful for sites of any size, especially busier sites
上述定义摘自Home - PHP-FPM
FPM配置
PHP-FPM作为进程管理器 (当然它不仅仅是进程管理器 详见上述讨论) 它的默认配置如下
cat /etc/php/7.0/fpm/pool.d/www.conf | grep -v '^$' | grep -v ';'
[www]
user = www-data
group = www-data
listen = /run/php/php7.0-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
ps ax | grep fpm -v grep
1244 ? Ss 2:49 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
15985 ? S 0:02 php-fpm: pool www
15986 ? S 0:01 php-fpm: pool www
17604 ? S 0:00 php-fpm: pool www
这里 有一个读者容易忽视的配置
listen = /run/php/php7.0-fpm.sock
那么 类似*.sock的listen方式和下面的配置有何区别呢
listen = 127.0.0.1:9000
答案就是
/run/php/php7.0-fpm.sock
1 Web Server与PHP-FPM的通信基于文件系统socket效率相对更高
2 但是仅限于Web Server与PHP-FPM在同一台服务器
127.0.0.1:9000
1 Web Server与PHP-FPM的通信基于网络TCP效率相对较低
2 但是Web Server与PHP-FPM可以不局限于同一台服务器
Nginx配置
当我们使用Nginx作为Web Server时 对于PHP项目的配置通常如下
server {
location / {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME /path/to/index.php;
}
}
cat /etc/nginx/fastcgi_params
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
fastcgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;
细心的读者 可能已经发现除了/etc/nginx/fastcgi_params还有/etc/nginx/fastcgi.conf
那么 两者的内容有何区别呢?
diff /etc/nginx/fastcgi_params /etc/nginx/fastcgi.conf -c
*** /etc/nginx/fastcgi_params Wed Nov 15 17:16:27 2017
--- /etc/nginx/fastcgi.conf Tue Apr 26 22:51:14 2016
***************
*** 1,4 ****
--- 1,5 ----
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
***************
*** 23,28 ****
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
-
- fastcgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
- fastcgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;
--- 24,26 ----
关于diff命令 更多参考diff
原来 由于很多开发者进行如下的硬编码
fastcgi_param SCRIPT_FILENAME /path/to/index.php;
所以 为了规范起见引入了/etc/nginx/fastcgi.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
参考
CGI specification
FastCGI Specification
CGI,FastCGI,PHP-CGI与PHP-FPM
搞不清FastCgi与PHP-fpm之间是个什么样的关系
Web Service(Nginx、Apache、IIS)、CGI、FastCGI与PHP-FPM概念、之间关系和处理流程
如何通俗地解释 CGI、FastCGI、php-fpm 之间的关系?
PHP FastCGI Example
如何正确配置Nginx+PHP
Performance of unix sockets vs TCP ports
PHP-FPM: Socket vs TCP/IP and sysctl tweaking