PHP 各种运行方式的不完整总结

这篇文章最后更新的时间在六个月之前,文章所叙述的内容可能已经失效,请谨慎参考!

TS 和 NTS

TS(Thread-Safety) 即线程安全,多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时进行数据加锁保护,其他线程不能同时进行访问该数据,直到该线程读取完毕,其他线程才可访问使用该数据,好处是不会出现数据不一致或者数据污染的情况,但耗费的时间要比 NTS 长。

NTS(None-Thread Safe) 即非线程安全,不提供数据访问保护,有可能出现多个线程先后或同时操作同一数据的情况,容易造成数据错乱(即脏数据),一般操作的执行时间要比 TS 短。

PHP 常用的 SAPI

SAPI (Server Application Programming Interface,服务端应用编程端口)

可以这样查看 php 当前的运行模式

echo php_sapi_name();

和 http 服务器的组合

php 自身提供 http 服务

  1. 在 cli 模式下实现一个 http 服务,例如 swoole 或 workerman
  2. php 的内置服务器

这时 php 可以直接提供 http 服务或者通过反向代理和其它 http 服务器组合使用。

php 的内置服务器是单进程单线程的,运行的效率并不高

cgi 模式

通过 php-cgi 和 http 服务器的组合,通常是 php-cgi + apache , nginx 不能直接支持 cgi 。 但现在已经很少这用部署了,因为 cgi 的性能并不好。 其实 cli 也能实现 cgi 的,但是要自行解释 标准输入 和 环境变量 里的参数,然后自行构造 http 的响应头。

fastcgi 模式

  1. 直接使用 php-cgi 对接 http 服务器,例如 windows 环境下的 nginx + php-cgi ,好像是因为 fpm 依赖 fork ,但 windows 里没有 fork ,所以 fpm 没有 windows 版
    • 如果一定要在 windows 运行 fpm ,可以尝试这些 windows 下的 linux 环境
      • wsl
      • 虚拟机
      • docker
      • cygwin
  2. 使用 fpm 对接 http 服务器,例如 linux 环境下的 nginx + fpm
  3. 使用一个 fastcgi 管理器,然后配置 php-cgi 对接 http 服务器,例如 nginx + spawn-fcgi + php-cgi

使用 php-cgi 时最好配置这个环境变量 PHP_FCGI_CHILDREN 。

PHP_FCGI_CHILDREN 默认值是 1 ,大致就是一个管理器,一个子进程,速度估计也就比 php 的内置服务器好一点。

如果 PHP_FCGI_CHILDREN 的值为 0 ,就只有一个子进程,那么只要累计的请求数达到 PHP_FCGI_MAX_REQUESTS , php-cgi 就会自动退出,继续有请求时 nginx 就会返回 502 。

php-cgi 没有平滑重启,修改 php.ini 后要重启 php-cgi 。

apache 模块

apache 模块的运行方式也是十分流行的运行方式。

这里需要注意的是,要根据 apache 的 mpm (Multi-Processing Module) 来选择 PHP 的版本。

mpm 的比较常用模式有四种。

PHP 官方不建议用线程化 MPM (比如 event ) 的 Apache 来跑 PHP https://www.php.net/manual/zh/faq.installation.php#faq.installation.apache2

总结

php 的运行模式有很多种。 现在 php 比较流行的部署方式,就只有两种

因为 swoole 的发展,在 cli 下实现 http 服务的运行方式也越来越流行了。

无论哪种运行方式,本质上都是 接收数据 处理数据 输出数据 三板斧。