Swoole底层架构
Swoole 主要包含以下组件:
- Master:当我们运行启动 Swoole 的 PHP 脚本时,首先会创建该进程(它是整个应用的 root 进程),然后由该进程 fork 出 Reactor 线程和 Manager 进程。
- Reactor:Reactor 是包含在 Master 进程中的多线程程序,用来处理 TCP 连接和数据收发(异步非阻塞方式)。Reactor 主线程在 Accept 新的连接后,会将这个连接分配给一个固定的 Reactor 线程,并由这个线程负责监听此 socket。在 socket 可读时读取数据,并进行协议解析,将请求投递到 Worker 进程;在 socket 可写时将数据发送给 TCP 客户端。
- Manager:Manager 进程负责 fork 并维护多个 Worker 子进程。当有 Worker 子进程中止时,Manager 负责回收并创建新的 Worker 子进程,以便保持 Worker 进程总数不变;当服务器关闭时,Manager 将发送信号给所有 Worker 子进程,通知其关闭服务。
- Worker:以多进程方式运行,每个子进程负责接受由 Reactor 线程投递的请求数据包,并执行 PHP 回调函数处理数据,然后生成响应数据并发给 Reactor 线程,由 Reactor 线程发送给 TCP 客户端。所有请求的处理逻辑都是在 Worker 子进程中完成,这是我们编写业务代码时真正要关心的部分。
- Task Worker:功能和 Worker 进程类似,同样以多进程方式运行,但仅用于任务分发,当 Worker 进程将任务异步分发到任务队列时,Task Worker 负责从队列中消费这些任务(同步阻塞方式处理),处理完成后将结果返回给 Worker 进程。
php-fpm 和 Swoole 的主要区别
php在php-fpm中的生命周期
在传统的 php-fpm 中,php是没有web服务器的,需要借助 Nginx (Apache)来做为web服务器,然后 php-fpm 通过 Fastcgi 协议,接收 Nginx 传过来的请求,而 php-fpm 是 Master/Worker 运行模式,php-fpm 启动时,会常驻运行一个 Master 进程,来监听来自 Nginx的请求。当Master主进程收到来自 Nginx 的请求时候,就会fork多个Worker进程,来处理请求(每个Worker进程只能处理一个请求),一个Worker进程生命周期如下:
- 初始化模块
- 初始化请求(指初始php代码请求,不是http)
- 执行php脚本
- 结束请求
- 关闭模块
这也是PHP不适合高并发的根本原因,每处理一个http请求,PHP-FPM就会建立一个worker进程来处理,处理完请求在关闭,无论是建立或者销毁还是初始化,都会导致内存和cpu的消耗巨大(PHP是多进程的)
php在Swoole中的生命周期
在swoole中,接收一个http请求,是不需要借助Nignx这类第三方的web服务器,swoole会自已建立一个或者多个端口负责监听来处理请求,相当于swoole自已一个就做了Nginx+php-fpm的工作。
swoole采用的也是Master/Worker进程模式,不同的是Master进程下有多个Reactor线程,Master进程只负责监听Socket句柄的事件变化(类似监听对外开发的接口),而请求由Reactor线程接收和处理(处理TCP请求),并转发给Worker进程执行回调函数(PHP编写的代码),所以swoole启动的时候,需要常驻运行Master进程,启动过程如下:
- 初始化模块
- 初始化请求(与php-fpm不一样,php-fpm是每次请求都会初始化,而swoole只是启动的时候才初始化
- 执行PHP脚本(没有结束和关闭,Master进程会进入监听状态)
swoole(或者是基于swoole开发的hyperf框架)都是由cli(命令行方式)运行的
对比总结
从上面比较不难看出,swoole和php-fpm的生命周期不一样。php-fpm每次接受请求都会执行一遍php代码,而swoole只会在启动的时候执行一次php代码的编译,所以在实际开发的时候,会发现传统的php-fpm在改php代码的时候,刷新网页http请求就能看到php代码的变化,但是swoole不会,swoole需要重新运行和编译才能看到代码的变化。
Swoole如何实现高并发
因为reactor基于epoll,所以每个reactor可以处理很多个连接请求。 如此,swoole就轻松的处理了高并发。
Swoole如何实现异步I/O
swoole的worker进程有2种类型:一种是普通的worker进程,一种是task worker进程。
- worker进程是用来处理普通的耗时不是太长的请求;
- task worker进程用来处理耗时较长的请求,比如数据库的I/O操作。
如此,通过worker、task worker结合的方式,我们就实现了异步I/O。
Swoole技术特点
- 常驻内存,避免重复加载带来的性能损耗,提升海量性能;
- 基于epoll,轻松支持高并发;
- 协程异步I/O,提高对I/O密集型场景并发处理能力;
- 支持多种通信协议,方便地开发 Http、WebSocket、TCP、UDP 等应用