1.PHP的架构
架构图1(来源网络)
架构图2(来源网络)
从上图可以看出,PHP基本是一个4层的架构体系:可以分为
zend引擎,sapi层,扩展层,应用层
-
Zend引擎:
C写的一个引擎,将PHP代码翻译成opcode,提供zend api,数据结构,内存管理
-
Extensions: 组件式提供
服务,如内置函数,标准库,其他的如pdo,curl等,
也可以自行安装其他扩展 -
sapi : php提供的一个跟
外部通信的接口
,使得PHP可以与外围交互数据,PHP提供很多sapi,比如
cli、fpm ,apache2handler
等 -
应用层:就是phper编写的
PHP程序
,通过不同的
sapi方式得到各种各样的应用模式
2.php的运行模式
PHP一共分为五大运行模式
- cgi (通用网关接口 Common Gateway Interfave)
- fast-cgi (fast-cgi是cgi的升级版本, php-fpm就是fast-cgi的一个实现)
- cli (Common Line Interface)
- isapi (微软提供的一套面向Internet的API接口)
- apache2handler (作为Apache的模块运行)
CLI模式
Common Line Interface的简称,即
PHP命令行接口,win跟Linux下都支持PHP-CLI模式
。
比如: php test.php
应用场景:定时任务,shell脚本,桌面应用(PHP-CLI和GTK包)
CGI模式
CGI即通用网关接口(Common Gateway Interface), 通俗的讲CGI就像是一座桥,
把网页和Web服务器中的执行程序连接起来,它把http服务器接收的指令传递给执行程序,
再把结果返回给http服务器。CGI的跨平台性能极佳,几乎可以在任何操作系统上实现。
执行过程:如访问index.php,http服务器接收到请求后,会通过它配置的CGI服务去执行,生成一个php-cgi.exe的进程,并执行php程序,执行结果返回给http服务器。
应用场景:提供http服务
优点和缺点:跨平台,几乎可以在任何操作系统上实现,web和server是独立的,结构清晰,可控性强,性能比较差,来一个请求,
fork一个进程,100个请求就会fork100进程
,消耗资源较多
FastCGI模式
FastCGI即快速通用网关接口(Fast Common Gateway Interface/ FastCGI)是上面CGI的增强版本
。FastCGI致力于减少Web服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的网页请求。
执行过程:
web服务器启动时,载入FastCGI进程管理器,FastCGI进程管理器会启动多个CGI进程等待服务器的链接
。当请求到达,FastCGI分配一个子进程php-cgi去处理,子进程处理结束后会自动处于等待状态状态并等待处理下一个分配请求
应用场景:提供http服务
优点缺点:跨平台,web跟server相互独立,支持大并发,多进程,消耗内存
模块模式:
PHP作为web服务器的一个模块去被调用
,如Apache的apache2handler,Apache监听到一个用户请求index.php,然后apache根据conf文件的配置去调用PHP
应用场景:http服务
优缺点:安装配置方便,不需要安装代码解析程序,支持多线程,占用资源少,支持大并发
3.PHP的线程安全与非线程安全
线程的安全与否就是取决于
是否给线程读取的数据加锁
,给数据加锁了避免脏数据就是线程安全
PHP提供TS和NTS版本(线程安全与非线程安全)
比如:如果PHP以ISAPI方式加载,模块方式嵌入Apache 的时候我们需要选择线程安全的版本(TS版本),原因是
PHP以这种形式的情况下被安装时,PHP没有独立的进程,而是作为模块被加载运行
,这时候以来于web服务器进程的,而当
web服务器刚好是在运行多线程模式(eg:IIS)这时PHP自然也就在多线程环境下
而当
PHP以FastCGI方式安装时,PHP拥有独立的进程,而且FastCGI是单一线程的
,不存在多个线程之间的相互干扰。(省去了线程安全的检查,因此FastCGI方式也比ISAPI的效率更高),所以FastCGI情况下无需考虑线程安全与非线程安全。
4.web服务器的选择
为什么大访问量下Nginx的性能更高?
Apache所采用的select网络 I/O 模型非常低效
Nginx使用了最新的
epoll (Linux2.6内核) 和kqueue(freebsd) 网络I/O模型
其次Apache进程干的事情多:执行PHP,输出HTML都得干,占用的资源就多(CPU,内存)
关于选择
- Apache的模块非常丰富,使用到它的模块就选它
- Apache的rewrite非常强大,rewrite多就选它
- 大并发选Nginx
- Nginx本质上是反向代理服务器,需要反向代理就选它
5.PHP-FPM与Swoole,Workerman对比
1.PHP-FPM:
我们在用传统的PHP-FPM框架去进行Web开发时,通常要结合Web服务器,比如Nginx,那是因为PHP内部并没有封装对应的Web网络服务,
PHP-FPM本质上只是一个CGI,是一个连接Web服务器跟PHP程序的一座桥梁
。
工作原理
:PHP-FPM就是一个FastCGI的一个实现,他的工作原理如下:
PHP-FPM启动后,会启动多个fast-cgi进程并监听端口,等待Nginx转发请求给php-fpm处理
。当接收到web服务器转发的请求,php-fpm就会把请求交给一个空闲的进程处理。
进程模型
:
- PHP-FPM采用的是Master / Worker进程模型。
- Master进程负责管理Worker进程,监听端口
- Worker进程负责处理业务逻辑
2.Swoole
简单来说Swool
e就是用C写的一个PHP的网络扩展(上面讲php-fpm时我们提到php自己没有封装网络服务,fpm需要依赖Nginx
)。当然,Swoole提供了很多强大的功能,比如协程,TCP/UDP服务,socket通讯等等,极大的拓宽了PHP的应用场景。
工作原理: Swoole是PHP的一个扩展,但是他又不是普通的扩展,其最明显的特点就是:一旦运行后就会接管PHP的控制权,进入事件循环。当某种IO事件发生时(网络IO),swoole会回调开发者设定的指定的PHP函数;其实这里面swoole是承担起底层网络事件的监听及底层事件的处理,当收到请求时就把控制权转交给预先注册的事件回调函数。
<?php
//new一个swooleServer对象并指定监听端口和运行模式,以及Socket类型
$server = new Swoole\Server('0.0.0.0',9501,SWOOLE_PROCESS,SWOOLE_SOCK_TCP);
//设置运行参数
$server->set([
'worker_num'=>4, //工作进程数量
'daemonize'=>true, //是否以守护进程模式运行
'backlog'=>128, //listen队列长度
]);
//注册事件回调函数
//这里指当底层Tcp新连接进入事件时,交给TCP类的onConnect静态方法处理
$server->on('Connect',[Tcp::class,'onConnect']);
//这里指当收到数据时,交给TCP类的onReceive静态方法处理
$server->on('Receive',[Tcp::class,'onReceive']);
//这里指当tcp客户端连接关闭时,交给tcp类的onClose静态方法处理
$server->on('Close',[Tcp::class,'onClose']);
进程模型(SWOOLE_PROCESS模式下):
-
Master进程:
Master进程时swoole的核心进程,也是一个多线程的进程
。Master线程用于accept新的连接,然后Reactor线程当一个socket可读或可写的时候,就由Reactor线程将事件转发给worker进程 -
Manager进程:
管理Worker进程和Task进程
,Worker进程和Task进程时由Manger进程fork出来的。 -
Worker进程:worker进程是由Manager进程fork而来的,
用于处理具体的业务逻辑
。Worker进行可以用同步的方式去干活,也可以用异步的方式去干活。 -
Task进程:
Task进程是一种特殊的Worker进程,专门用于处理一些比较耗时的操作
。Task进程只能工作在同步的方式下,不能使用异步。
3.workerman(简单介绍)
通俗的讲workerman就是用PHP写的一个更底层更通用的
网络服务框架
实际上workerman类似一个PHP版本的Nginx,核心也是多进程+Epoll+非阻塞io。workerman每个进程能维持上万并发连接。由于本身常驻内存,不依赖Apache,Nginx,PHP-FPM这些容器,所以永远超高的性能。
对应的框架
- 1.传统的fpm框架:如laravel,thinkPHP等等
- 2.swoole类的框架:Hyperf,Swoft等
- 3.workerman类的框架:webman等