swoole进程模型 Reactor、manager、Worker、Task的关系
swoole的进程理解是一个有点点烧脑的地方,但是理解了还是简单,官方的文档其实说得比较具体,但是不够直观
自己重新整理下
=============================官方文档===============================
三种角色分别的职责是:
Reactor线程
负责维护客户端机器的TCP连接、处理网络IO、收发数据 完全是异步非阻塞的模式 全部为C代码,除Start/Shudown事件回调外,不执行任何PHP代码 将TCP客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包 Reactor以多线程的方式运行
Worker进程
接受由Reactor线程投递的请求数据包,并执行PHP回调函数处理数据 生成响应数据并发给Reactor线程,由Reactor线程发送给TCP客户端 可以是异步非阻塞模式,也可以是同步阻塞模式 Worker以多进程的方式运行
Task进程
接受由Worker进程通过swoole_server->task/taskwait方法投递的任务 处理任务,并将结果数据返回给Worker进程 完全是同步阻塞模式 Task以多进程的方式运行 关系
可以理解为reactor就是nginx,worker就是php-fpm。reactor线程异步并行地处理网络请求,然后再转发给worker进程中去处理。reactor和worker间通过IPC方式通信。
swoole的reactor,worker,task_worker之间可以紧密的结合起来,提供更高级的使用方式。
一个更通俗的比喻,假设Server就是一个工厂,那reactor就是销售,帮你接项目订单。而worker就是工人,当销售接到订单后,worker去工作生产出客户要的东西。而task_worker可以理解为行政人员,可以帮助worker干些杂事,让worker专心工作。
底层会为Worker进程、Task进程分配一个唯一的ID 不同的task/worker进程之间可以通过sendMessage接口进行通信
=============================官方文档完===============================
以上是官方的文档的说明
我做点补充,首先为了区分清楚进程,我们对程序做如下的设置
public function onWorkerStart($server, $worker_id)
{
if ($worker_id >= $server->setting['worker_num']) {
swoole_set_process_name('php ' . $argv[0] . ' task');
} else {
swoole_set_process_name('php ' . $argv[0] . ' worker');
}
}
public function onStart()
{
swoole_set_process_name('php : master ');
}
public function onManagerStart()
{
global $argv;
swoole_set_process_name('php ' . $argv[0] . ': manager');
}
这段代码的意思 其实很简答就是给不同的进程重命名,当然我们为了保证能有task进程出现,还需要定义
$this->server = new swoole_http_server('0.0.0.0', 8002);
$this->server->set([
'worker_num' => 12,
'task_worker_num' => 8,
'daemonize' => false,
'log_file' => './log'
]);
{PS:这两段代码只是部分截取,需要补充其他程序代码才能运行}
运行之后,我们能看到如下的进程列表
root 14315 12977 0 11:52 pts/2 00:00:00 php sms_server.php: master
root 14316 14315 0 11:52 pts/2 00:00:00 php sms_server.php: manager
root 14321 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14322 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14323 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14324 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14325 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14326 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14327 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14328 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14329 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14330 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14331 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14332 14316 0 11:52 pts/2 00:00:00 php sms_server.php worker
root 14333 14316 0 11:52 pts/2 00:00:00 php sms_server.php task
root 14334 14316 0 11:52 pts/2 00:00:00 php sms_server.php task
root 14335 14316 0 11:52 pts/2 00:00:00 php sms_server.php task
root 14336 14316 0 11:52 pts/2 00:00:00 php sms_server.php task
我们可以很清楚的看到,因为我们前面重命名了进程的名字,所以我们的进程 有master manager worker task
master其实就是主进程,也就是前面官方文档说的Reactor线程,具体的作用官方的文档说得很清楚了
manager 进程,其实manager进程并没有参与业务执行过程,他的左右只是根据你的配置管理worker进程的数量,死了的拉起来
worker 就是具体做事情的进程了
task 其实就是一个mini的worker,他可以接受worker投递过来的任务
master(收发网络)->worker(执行)->task(worker不想做的分给task)
用一个三俗的比喻吧
master 就是小发廊门口拉客的皮条客,他只负责拉客和送客,有客人来呢,他就把客人送给物理具体做活儿的技师(worker),有技师去服务
技师(worker),比较忙的时候,她有可以把客人,分给其他的比他地位低的,差一点的助理技师(task)去帮他服务,
如果说技师,直接把客人交代给了助理技师,自己直接去接下一个客人,不等助理技师服务完呢,这个是swoole_server->task非阻塞
如果说技师对助理技师的活儿不放心,一直等着助理技师服务完了,再接着去做活儿呢 这个是swoole_server->task 阻塞的task
至于manager呢,其实就是个鸡头罢了,他的任务呢就是保证今天有多少个技师在店里,如果说某个技师中途跑了或者不能上钟了,他就再安排一个
如此这般 介绍完毕
对皮条业务这么熟悉,看来是常客啊