SAPI是PHP框架的接口层,是进入PHP内部的入口,PHP中实现的SAPI有很多。

常用的主要是:

  • Cli
  • Fpm
  • Embed

Cli

   Cli,即命令行接口,用于在命令行下执行PHP脚本,类似于shell那样。Cli模式通过执行编译的PHP二进制程序即可启动,可通过定义的命令行参数来对应不同的处理。

1
2
3
4
5
//执行PHP脚本
$ php hello.php

//查看PHP已安装的扩展
$ php -m

Cli是单进程模式,处理完请求后直接关闭,经历整个PHP生命周期,关键过程如下:
main() -> php_cli_startup() -> do_cli() -> php_module_shutdown()

Fpm (FastCGI Process Manager)

   Fpm是PHP FastCGI运行模式的一个进程管理器,核心功能就是进程管理。

   FastCGI本身是web服务器和处理程序之间的一种通信协议,是类似于HTTP的一种应用层协议,没错,就是一种协议!
在网络应用场景下,PHP并没有实现自身的HTTP网络库,而是实现了FastCGI协议,与web服务器配合实现了HTTP处理。web服务器处理HTTP请求,然后将解析的结果通过FastCGI协议转发给处理程序,处理程序处理完了将结果返回给web服务器,web服务器再返回给用户。

Fpm的基本实现

   Fpm是一种多进程模型,由一个master进程和多个worker进程组成。master进程启动时会创建一个socket,但是不接收和处理请求,而是由fork出的worker子进程来完成。

   master进程的主要工作还是管理worker进程,负责fork和kill worker进程,比如请求多的时候,worker处理不过来,就fork新的,而空闲的时候就kill掉多余的worker,避免占用浪费系统资源。

   worker进程的主要工作是处理请求,每个worker会竞争Accept请求,接收成功后解析FastCGI,然后执行相应的脚本,处理完成后关闭请求,等待新的连接。需要指明的是一个worker进程只能处理一个请求,这与Nginx的事件模型有很大区别,Nginx的子进程通过epoll管理套接字,如果一个请求数据还没有发送完成则会处理下一个请求,每一个进程会同时接收多个请求,是非阻塞的模型,只处理活跃的套接字。Fpm的这种处理模式大大简化了PHP的资源管理,不需要考虑并发导致的资源冲突,从这一点来看,php处理高并发业务时性能的确是差些。

   master和worker 进程之间不会直接进行通信,master通过共享内存获取worker的信息,如worker进程当前的状态,已处理的请求数等,master通过发送信号的方式kill掉worker进程。

   Fpm可以同时监听多个端口,每个端口对应一个worker pool,每个pool下对应多个worker进程,这个有点类似nginx中的server概念,这个归属不同pool的worker进程仍由master来管理。

Embed

   如果我们想在第三方应用中使用PHP,比如开发一个路由器,想嵌入PHP实现web配置的功能,PHP提供了一个用于这类场景的SAPI——Embed;它在编译后就是普通的库文件,可以在C/C++应用中调用PHP提供的API。