Master 进程、Reactor 线程、Worker 进程、Task 进程、Manager 进程的区别与联系
首先得明白进程是什么线程是什么?
进程是资源分配的最小单位,线程是CPU调度的最小单位。
如果打个比方,好比进程是一个火车,线程就是火车厢,线程必须在进程下运行,没有火车厢的火车不是好火车,进程可以包含很多线程。火车可以有很多车厢,同一进程下线程是共享的,比如a车厢到b车厢,进程和进程之间不会相互影响,相互独立,比如和谐号和复兴号。进程下的线程挂掉会影响到进程,车厢销毁,火车也不存在了。
Master 进程
Master 进程是一个多线程进程(多火车厢的火车)
Reactor 线程
可以理解为Reactor 就是 nginx,Reactor 线程异步并行地处理网络请求,然后再转发给 Worker
进程中去处理。Reactor 和 Worker 间通过 unixSocket(.sock文件) 进行通信。
1.Reactor 线程是在 Master 进程中创建的线程
2.负责维护客户端 TCP 连接、处理网络 IO、处理协议、收发数据
3.不执行任何 PHP 代码
4.将 TCP 客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包
Worker 进程
可以把Worker进程想象成php-fpm,接受Nginx(Reactor线程)的调度任务
1.接受由 Reactor 线程投递的请求数据包,并执行 PHP 回调函数处理数据
2.生成响应数据并发给 Reactor 线程,由 Reactor 线程发送给 TCP 客户端
3.可以是异步非阻塞模式,也可以是同步阻塞模式
4.Worker 以多进程的方式运行
TaskWorker 进程
1.接受由 Worker 进程通过 Swoole\Server->task/taskwait/taskCo/taskWaitMulti 方法投递的任务
处理任务,并将结果数据返回(使用 Swoole\Server->finish)给 Worker 进程
2.完全是同步阻塞模式
3.TaskWorker 以多进程的方式运行,task 完整示例:
$serv = new Swoole\Server('127.0.0.1', 9501);
//设置异步任务的工作进程数量
$serv->set([
'task_worker_num' => 4
]);
//此回调函数在worker进程中执行
$serv->on('Receive', function($serv, $fd, $reactor_id, $data) {
//投递异步任务
$task_id = $serv->task($data);
echo "Dispatch AsyncTask: id={$task_id}\n";
});
//处理异步任务(此回调函数在task进程中执行)
$serv->on('Task', function ($serv, $task_id, $reactor_id, $data) {
echo "New AsyncTask[id={$task_id}]".PHP_EOL;
//返回任务执行的结果
$serv->finish("{$data} -> OK");
});
//处理异步任务的结果(此回调函数在worker进程中执行)
$serv->on('Finish', function ($serv, $task_id, $data) {
echo "AsyncTask[{$task_id}] Finish: {$data}".PHP_EOL;
});
$serv->start();
Manager 进程
负责创建 / 回收 worker/task 进程
在 PHP-FPM 的应用中,经常会将一个任务异步投递到 Redis 等队列中,并在后台启动一些 PHP进程异步地处理这些任务。Swoole 提供的 TaskWorker 是一套更完整的方案,将任务的投递、队列、PHP任务处理进程管理合为一体。通过底层提供的 API 可以非常简单地实现异步任务的处理。另外 TaskWorker还可以在任务执行完成后,再返回一个结果反馈到 Worker进程中。
一个更通俗的比喻,假设 Server 就是一个餐馆,那 Reactor 就是服务员,接受客户点菜。而 Worker 就是厨子,当服务员接到订单后,Worker(厨子) 去炒菜,生产出客户要的菜。而 TaskWorker 可以理解为打杂厨子,可以帮助 Worker (厨子)干些杂事(比如Worker厨子要炒菜,TaskWorker打杂厨子可以帮Worker厨子备菜、清洗工具),让 Worker厨子 专心工作。