PHP的运行模式

基本概念

CGI 通用网关接口  Common Gateway Interface

CGI 是Web 服务器运行外部程序的规范(协议),按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为HTML文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。几乎所有服务器都支持CGI,可用任何语言编写CGI,包括流行的C、C ++、VB 和Delphi 等。CGI 分为标准CGI 和间接CGI两种。标准CGI 使用命令行参数或环境变量表示服务器的详细请求,服务器与浏览器通信采用标准输入输出方式间接CGI 又称缓冲CGI,在CGI 程序和CGI 接口之间插入一个缓冲程序,缓冲程序与CGI 接口间用标准输入输出进行通信。

功能,处理浏览器发送的表单请求,处理后并给浏览器响应(HTML).PHP就是C语言编写的CGI程序.其它ASP,JSP, .NET等

简而言之,来自客户端的HTTP POST请求将通过标准输入发送CGI程序HTML表单数据。其他数据(如URL路径和HTTP标头数据)显示为过程环境变量。

缺点

每有一个用户请求,都会先要创建CGI的子进程,然后处理请求,处理完后结束这个子进程(Fork-And-Execute模式). 这种方式开销大,请求过多和高并发是占用系统资源多.

CGI结构图

FastCGI  快速通用网关接口 FastCommonGatewayInterface

FastCGI(一种二进制协议,用于将交互式程序与Web服务器连接)像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

每个单独的FastCGI进程可以在其生命周期内处理许多请求,从而避免了每个请求进程创建和终止的开销。同时处理多个请求可以通过几种方式实现:通过使用具有内部多路复用的单个连接(即通过单个连接的多个请求); 通过使用多个连接; 或者通过这些技术的组合。可以配置多个FastCGI服务器,从而提高稳定性和可扩展性。

进入正题

PHP结构图

SAPI

SAPI(Server Application Programming Interface,服务端应用编程端口 )是PHP的应用接口层,提供php和外部程序(web服务器和shell终端)通信的接口.PHP为不同的web服务器提供多种SAPI接口,运行模式指的就是PHP运行的是那种SAPI

获取SAPI http://php.net/manual/zh/function.php-sapi-name.php

 php_sapi_name() 和 PHP_SAPI 返回描述 PHP 所使用的接口类型(the Server API, SAPI)的小写字符串。 例如,CLI 的 PHP 下这个字符串会是 “cli”,Apache 下可能会有几个不同的值,取决于具体使用的 SAPI。 以下列出了可能的值。

可能返回的值包括了 aolserverapache、 apache2filterapache2handler、 caudiumcgi (直到 PHP 5.3), cgi-fcgicli、 cli-server、 continuityembedfpm-fcgi、 isapilitespeed、 milternsapi、 phttpdpi3webroxen、 thttpdtux 和 webjames

CLI模式

http://php.net/manual/zh/features.commandline.php

从版本 4.3.0 开始,PHP 提供了一种新类型的 CLI SAPI(Server Application Programming Interface,服务端应用编程端口)支持,名为 CLI,意为 Command Line Interface,即命令行接口。顾名思义,该 CLI SAPI 模块主要用作 PHP 的开发外壳应用。CLI SAPI 和其它 CLI SAPI 模块相比有很多的不同之处,我们将在本章中详细阐述。值得一提的是,CLI 和 CGI 是不同的 SAPI,尽管它们之间有很多共同的行为。

CLI-Server

PHP 5.4.0起, CLI SAPI 提供了一个内置的Web服务器。这个内置的Web服务器主要用于本地开发使用,不可用于线上产品http://php.net/manual/zh/features.commandline.webserver.php

CGI 模式

http://php.net/manual/zh/install.unix.commandline.php

LoadModule cgi_module modules/mod_cgi.so —cgi 模块 apache

FastCGI模式

FPM模式 

http://php.net/manual/zh/install.fpm.php

FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。

PHP-FPM 这种模型是非常典型的多进程同步模型,由一个master主进程多个worker进程组成.master进程创建时会创建一个sokect,但是不会处理请求,只负责调度worker进程

worker进程的生命周期,竞争的接受请求,解析FastCGI协议的数据,处理对应脚本,处理完成关闭请求,然后等待新的连接.同一时刻只能处理一个请求(同步阻塞IO).

master进程与worker进程之间不会直接通讯,master进程通过共享内存方式获取worker进程的信息,通过信号方式杀死worker进程.(进程间通讯)

缺点

每次启动都与需要重新加载php文件,浪费了一部分性能

ISAPI模式 (PHP 5.3)

ISAPI(Internet Server Application Program Interface)是微软提供的一套面向 Internet 服务的 API 接口,一个 ISAPI 的 DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个 DLL 里设置多个用户请求处理函数,此外,ISAPI 的 DLL 应用程序和 WEB 服务器处于同一个进程中,效率要显著高于 CGI。由于微软的排他性,只能运行于 Windows 环境。

Module 模式  

http://php.net/manual/zh/install.unix.apache2.php

PHP 常常与 Apache 服务器搭配形成 LAMP 配套的运行环境。把 PHP 作为一个子模块集成到 Apache 中,就是 Module 模式,Apache 中的常见配置如下:

LoadModule php5_module modules/mod_php5.so

这使用了 LoadModule 命令,该命令的第一个参数是模块的名称,名称可以在模块实现的源码中找到。第二个选项是该模块所处的路径。如果需要在服务器运行时加载模块,可以通过发送信号 HUP 或者 AP_SIG_GRACEFUL 给服务器,一旦接受到该信号,Apache 将重新装载模块,而不需要重新启动服务器。通过注册到 apache2 的 ap_hook_post_config 挂钩,在 Apache 启动的时候启动此模块以接受 PHP 文件的请求。

例如,当客户端访问 PHP 文件时,Apache 就会调用 php5_module 来解析 PHP 脚本。Apache 每接收到一个请求,都会产生一个进程来连接 PHP 完成请求。在 Module 模式下,有时候会因为把 PHP 作为模块编进 Apache,而导致出现问题时很难定位是 PHP 的问题还是 Apache 的问题。

Apache MPM(多处理模块) 选择

要求 更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event 需要可靠性或者与旧软件兼容的站点可以使用 prefork

运行方式总结

linux + nginx + php-fpm 主流 + 性能和兼容性兼顾

linux + nginx + php-cli + workman/webman 高性能 兼容原先的composer代码库

linux + nginx + php-cli (swoole-cli) 对旧代码兼容不好,如需要重建协程组件

linux + apache mpm event + php-fpm

linux + apache mpm + mod_php

I/O性能优先级

swoole(cli) > php-fpm > mod_php

相关参考

深入理解Zend SAPIs(Zend SAPI Internals) 鸟哥博客

PHP 运行模式

mod_php和mod_fastcgi和php-fpm的介绍,对比和性能数据

Apache的三种MPM模式比较:prefork,worker,event