NGINX
和 PHP
是一对很好的搭档,那么 nginx
是如何与 php
结合实现 对外的网络访问呢?
首先 NGINX
作为一个 web
服务器只能处理静态请求,关于动态请求,是通过 CGI
具备的动态请求能力。
NGINX会将动态请求交给 CGI
处理,CGI
将处理结果返回给 NGINX
,NGINX
再将请求的结果返给给浏览器
CGI 的作用
当在浏览器中输入一个动态地址时,如 /index.php
, 通过 DNS
解析,最终请求会到 web
服务器上,当 NGINX
发现请求时动态请求。会交给 PHP
解释器处理此请求,那再给 NGINX
需要给 PHP
解释器传输哪些数据呢?请求地址,请求方法,请求参数这些东西总归是要有的,但是也不能仅仅是这些,像请求头和 cookie
… 也应该包含其中。
那么怎么确定到底该传输哪些数据,以及以什么样的格式传输呢? CGI 就是解决这个问题而生的。
CGI 全程通用网关接口 (英语:Common Gateway Interface,CGI) 是为提供网络服务而执行控制台应用的程序,提供于服务器上实现动态网页的通用协议。通常情况下,一次请求对应一个CGI 脚本的执行,生成一个 HTML。
CGI 接口规定了 nginx 与动态解释器之前传输数据的参数和格式,为 nginx 和脚本解释器之间建立起了一个桥梁。
CGI 的存在使 web
服务器与动态语言之间的关系进行了解耦,使得 web 服务器可以处理的动态请求,但是 CGI 的设计使通过进程的方式来处理动态请求的,当动态请求过来后,CGI 会起一个进程进行处理,请求结束后关闭进程.
进程的频繁创建和销毁是存在开销的,这也就导致了 CGI 很难应对高并发的场景, FastCGI 的出现解决了这个问题.
FastCGI
快速通用网关接口(Fast Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。
FastCGI致力于减少 nginx 与CGI程序之间交互的开销,从而提升服务器处理并发的能力。
- Web Server 启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module,nginx 下 fastcgi 与服务器是分离的,fastcgi 可有 lighttpd 下的spawan-cgi或者 php-fpm 来管理));
- FastCGI进程管理器自身初始化,启动多个CGI解释器进程 (在任务管理器中可见多个php-cgi.exe)并等待来自Web Server的连接。
- 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi.exe。
- FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在WebServer中)的下一个连接。 在正常的CGI模式中,php-cgi.exe在此便退出了。
在上述情况中,你可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部dll扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
php-fpm 是什么
PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个PHPFastCGI管理器, 也就是说 FastCGI 是接口,php-fpm 是 FastCGI 的具体实现。php-fpm 专门用于执行 PHP 的代码,并将响应结果通过 NGINX 返回给浏览器。
Conclusion
NGINX 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。在 WEB 开发中主要用户处理静态文件的响应,其本身并不具备动态请求的解析能力。 CGI 是定义了一套接口,用于连接 NGINX 与动态语言,使 NGIXN 具备了动态请求的处理能力。
FastCGI: 为了解决 CGI 的性能问题,FastCGI 采用 master-worker 的形式,通过进程管理使得 CGI 能够处理多个请求,即不用频繁的创建和销毁进程,也不需要频繁的初始化配置,从而提升并发处理能力。
php-fpm: FastCGI 在 PHP 语言层面的具体实现,用于执行 PHP 代码。