三、Swoole 基础学习笔记 - 了解 Swoole 相关进程
3、Swoole 基础学习笔记 - 了解 Swoole 相关进程
hi,我是温新,一名PHPer
文章基于 Swoole 5.0 版本编写。
学习目标:了解 Swoole 是怎么工作的及相关进程。
说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
正所谓,"磨刀不误砍柴工",有了上篇文章的快速体验,本篇文章将了解 Swoole 相关进程,以便更好的了解 Swoole 的运行过程。
准备工作
安装 网络管理工具和进程管理工具。
# deepin
apt -y install net-tools psmisc
# Rocky Linux
dnf -y install net-tools psmisc
通过这两个工具来分析 Swoole 启动后的进程。
Swoole 是如何运行的
本篇文章会延续 Swoole 基础学习笔记 - 先把 Swoole 跑起来 案例来了解相关进程及线程。在这之前要先来了解一下 Swoole 是如何运行的。
Swoole 运行流程图
基于这个运行流程图,我们来看看 $server->start();
发生了什么。服务启动后如有如下操作:
Swoole 服务启动后发生的事
:启动成功后会创建 worker_num + 2
个进程。 Master 进程
+ Manager
进程 + serv->worker_num
个进程。比如说当我们设置进程数为 2 时,实际上启动了 4 个进程;结合运行流程图来看,服务启动后会创建 Master 进程、Worker 进程。
现在我们来总结下 Swoole 进程模型:Master - Manager - Worker
进程。这也是为什么设置 worker_num
进程启动后,查看进程会多出两个进程的原因,而这两个进程就是 master 进程和 manager 进程。
Swoole 进程/线程结构图
接下来再看看这些进程和线程都有什么作用,如下:
Master 进程
:为主进程,主进程中有多个 Reactor
线程,基于 epoll/kqueue
进行网络事件轮询。收到数据后转发到 Worker
进程去处理;
Manager 进程
:为管理进程,是对所有 Worker
进程生命周期结束或发生异常时自动回收,并创建新的 Worker
进程;
Worker 进程
:为工作进程,对收到的数据进行处理,包括协议解析和响应请求(未设置 worker_num
,底层会启动与 CPU
数量一致的 Worker
进程);
Task 进程
:异步工作进程,接收由Worker进程投递的任务,TaskWorker以多进程的方式运行,是同步阻塞模式;
Reactor 线程
:reactor 线程由 master 进程创建,reactor 负责维护客户端 TCP 连接、处理网络 IO、处理协议、收发数据。
了解了 Swoole 进程与线程,那么他们之间有什么关系呢?用个通俗的例子来说明,Server
是饭馆,Reactor
是服务员,Worker
是厨师。服务员将菜单拿给客户,点完菜后,服务员将菜单拿给大厨,在这个过程中,Worker
去生产客户所需要的菜,TaskWorker
可以理解为大厨的徒弟,可以帮助大厨干些琐事。
Swoole 启动后的进程与线程
结合上述知识,我们现在来看看 Swoole Server 启动后的进程与线程,
查看 Master 进程
$netstat -nltp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
# 9501,我们启动的 server 服务,这是 master 主进程
tcp 0 0 0.0.0.0:9501 0.0.0.0:* LISTEN 76459/php
查看进程树
$pstree -p 76459
# 76459 master 进程;
# 76460 manager 进程
# 76467... worker 进程
# 76461... 线程
php(76459)─┬─php(76460)─┬─php(76467)
│ ├─php(76470)
│ ├─php(76471)
│ ├─php(76472)
│ ├─php(76473)
│ ├─php(76474)
│ ├─php(76475)
│ ├─php(76476)
│ ├─php(76477)
│ ├─php(76478)
│ ├─php(76479)
│ ├─php(76480)
│ ├─php(76481)
│ ├─php(76482)
│ ├─php(76483)
│ └─php(76484)
├─{php}(76461)
├─{php}(76462)
├─{php}(76463)
├─{php}(76464)
├─{php}(76465)
├─{php}(76466)
├─{php}(76468)
└─{php}(76469)
通过进程树可以清晰看出进程间的关系,76459 master 进程下有线程,76460 manager 进程下有 worker进程。查看了进程与线程,有了这样一丝疑惑,怎么有这么多进程与线程?
当没有设置进程时,Swoole 线程与电脑 CPU 核数有关,我的电脑 CPU 为 8 核,因此有 8 个线程。这个值是可以配置的,下面我们就来看看。
set 方法设置进程数与线程数
set()
用于设置运行时的各项参数。服务器启动后通过 $serv->setting
来访问 Server->set
方法设置的参数数组。
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);
$server->set([
// 设置 3 个 worker 进程
'worker_num' => 3,
// 设置 2 个 reactor 线程
'reactor_num' => 2,
]);
$server->on('Connect', function ($server, $fd) {
});
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
$server->send($fd, '服务器返回:' . $data) . PHP_EOL;
});
$server->on('Close', function ($server, $fd) {
});
$server->start();
修改文件后需要中断服务,然后再重新启动才能生效。当前设置 worker_num
为 3 个进程后,猜一猜会启动多少个进程?答案是会启动 5 个进程,如果不明白为什么会启动 5 个进程,可以看看上面的内容。
$pstree -p 91875
php(91875)─┬─php(91876)─┬─php(91879)
│ ├─php(91880)
│ └─php(91881)
├─{php}(91877)
└─{php}(91878)
设置进程名称
为了更好的区分是什么是进程,现在来引入一些还没有学习到的知识——事件回调,以及用来设置进程名称的函数 swoole_set_process_name
,下来就直接来看案例吧:
<?php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);
$server->set([
'worker_num' => 3,
// task 任务进程
'task_worker_num'=> 2,
]);
$server->on('Connect', function ($server, $fd) {
});
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
});
// 设置 task 进程后,必须调用任务回调,不然会报错
$server->on('Task', function (Swoole\Server $server, Swoole\Server\Task $task) {
});
$server->on('Start', function ($server) {
swoole_set_process_name('swoole:master');
});
$server->on('ManagerStart', function ($server) {
swoole_set_process_name('swoole:manager');
});
$server->on('WorkerStart', function ($server, $workerId) {
if($workerId >= $server->setting['worker_num']) {
swoole_set_process_name("swoole:task worker");
} else {
swoole_set_process_name("swoole:php worker");
}
});
$server->on('Close', function ($server, $fd) {
});
$server->start();
现在为进程设置了名称,我们就来看看设置进程名称的进程情况:
$ps aux | grep swoole
codeing 97668 0.4 0.1 335168 27444 pts/1 Sl+ 23:50 0:00 swoole:master
codeing 97669 0.0 0.0 115996 10416 pts/1 S+ 23:50 0:00 swoole:manager
codeing 97673 0.0 0.0 118048 8704 pts/1 S+ 23:50 0:00 swoole:task worker
codeing 97674 0.0 0.0 118048 8712 pts/1 S+ 23:50 0:00 swoole:task worker
codeing 97675 0.0 0.0 118192 11460 pts/1 S+ 23:50 0:00 swoole:php worker
codeing 97676 0.0 0.0 118192 11460 pts/1 S+ 23:50 0:00 swoole:php worker
codeing 97677 0.0 0.0 118192 11460 pts/1 S+ 23:50 0:00 swoole:php worker
codeing 97682 0.0 0.0 13864 836 pts/2 S+ 23:51 0:00 grep swoole
现在可以很清晰的看哪个是 master,哪个是manager等进程了。 好了,本篇文章到此结束,我是温新。