5.swoole结构与网络io模型

本文详细介绍了Swoole的进程结构模型,包括Master、Manager、Worker和TaskWorker进程的作用和交互方式。此外还提供了Swoole进程可以绑定的事件及其应用场景。
1. swoole 进程结构
Swoole 的高效不仅仅于底层使用 c 编写,他的进程结构模型也使其可以高效的处理业务,我们想要深入学习,并且在实际的场景当中使用必须了解,下面我们先看一下结构图:

如上分为四层 :
1. master :主进程
2. Manger :管理进程
3. worker :工作进程
4. task :异步任务工作进程
 
1.1 master
第一层, Master 进程,这个是 swoole 的主进程 , 这个进程是用于处理 swoole 的核心事件驱动的,那么在这个进程当中可以看到它拥有一个 MainReactor[ 线程 ] 以及若干个 Reactor[ 线程 ] swoole 所有对于事件的监听都会在这
些线程中实现,比如来自客户端的连接,信号处理等。

 
 
MainReactor (主线程)
主线程会负责监听 server socket ,如果有新的连接 accept ,主线程会评估每个 Reactor 线程的连接数量。将此连接分配给连接数最少的 reactor 线程,做一个负载均衡。
 
Reactor 线程组
Reactor 线程负责维护客户端机器的 TCP 连接、处理网络 IO 、收发数据完全是异步非阻塞的模式。 swoole 的主线程在 Accept 新的连接后,会将这个连接分配给一个固定的 Reactor 线程,在 socket 可读时读取数据,并进行协
议解析,将请求投递到 Worker 进程。在 socket 可写时将数据发送给 TCP 客户端。
 
心跳包检测线程( HeartbeatCheck
Swoole 配置了心跳检测之后,心跳包线程会在固定时间内对所有之前在线的连接发送检测数据包
 
UDP 收包线程( UdpRecv
接收并且处理客户端 udp 数据包
 
 
 
 
 
1.2 manager
第二层, Master进程。
Swoole 想要实现最好的性能必须创建出多个工作进程帮助处理任务,但 Worker 进程就必须 fork 操作,但是 fork 操作是不安全的,如果没有管理会出现很多的僵尸进程,进而影响服务器性能,同时 worker进程被误杀或者由于程序的原因会异常退出,为了保证服务的稳定性,需要重新创建 worker 进程。
 
Swoole 在运行中会创建一个单独的管理进程,所有的 worker 进程和 task 进程都是从管理进程 Fork 出来的。管理进程会监视所有子进程的退出事件,当 worker 进程发生致命错误或者运行生命周期结束时,管理进程会回收
此进程,并创建新的进程。换句话也就是说,对于 worker task 进程的创建、回收等操作全权有 保姆 ”Manager 进程进行管理。
 
 
2.3 worker
worker 进程属于 swoole 的主逻辑进程,用户处理客户端的一系列请求,接受由 Reactor 线程投递的请求数据包,并执行 PHP 回调函数处理数据生成响应数据并发给 Reactor 线程,由 Reactor 线程发送给 TCP 客户端可以是异
步非阻塞模式,也可以是同步阻塞模式
 
2.4 task
taskWorker 进程这一进城是 swoole 提供的异步工作进程,这些进程主要用于处理一些耗时较长的同步任务,在 worker 进程当中投递过来。
 
 
3. 进程查看及流程梳理
 
当启动一个 Swoole 应用时,一共会创建 2 + n + m 个进程, 2 为一个 Master 进程和一个 Manager 进程,其中 n Worker 进程数。 m TaskWorker 进程数。
默认如果不设置, swoole 底层会根据当前机器有多少 CPU 核数,启动对应数量的 Reactor 线程和 Worker 进程。我机器为 1 核的。 Worker 1
所以现在默认我启动了 1 Master 进程, 1 Manager 进程,和 1 worker 进程, TaskWorker 没有设置也就是为 0 ,当前 server 会产生 3 个进程。
在启动了 server 之后,在命令行查看当前产生的进程
ps -aux | grep swool

执行结果:

 

当然我们也可以对于swoole的进程限制数量 
<?php 
// server 
$server->set([ 
    'worker_num'=>1, //设置进程 
]); 
?>
4. swoole 进程函数
 
事件 哪种类型的进程作用
onStart master进程

server启动

onStart回调中,仅允许echo、打印Log、修改进程名称。不得执行其他操作。onWorkerStart和onStart回调是在不同进程中并行执行的,不存在先后顺序。

onShutdownmaster进程

此事件在server正常结束时发生

强制kill进程不会回调onShutdown,如kill -9
在命令行中使用Ctrl+C中断程序会立即停止,底层不会回调onShutdown

需要使用kill -15来发送SIGTREM信号到主进程才能按照正常的流程终止

onManagerStart manager进程

当管理进程启动时调用它

 

onManagerStart触发时,说明:

  • TaskWorker进程已创建
  • Master进程状态不明,因为ManagerMaster是并行的,onManagerStart回调发生是不能确定Master进程是否已就绪
onManagerStop manager进程

当管理进程结束时调用它

onManagerStop触发时,说明TaskWorker进程已结束运行,已被Manager进程回收。

onWorkError manager进程

当worker/task_worker进程发生异常后会在manager进程内回调此函数

此函数主要用于报警和监控,一旦发现Worker进程异常退出,那么很有可能是遇到了致命错误或者进程CoreDump。通过记录日志或者发送报警的信息来提示开发者进行相应的处理。常见错误可以去手册查看

onWorkerStart worker进程

此事件在Worker进程/Task进程启动时发生

 

  • onWorkerStart/onStart是并发执行的,没有先后顺序
  • 可以通过$server->taskworker属性来判断当前是Worker进程还是Task进程
  • 设置了worker_numtask_worker_num超过1时,每个进程都会触发一次onWorkerStart事件,可通过判断$worker_id区分不同的工作进程
  • 由 worker 进程向 task 进程发送任务,task 进程处理完全部任务之后通过onFinish回调函数通知 worker 进程。例如,我们在后台操作向十万个用户群发通知邮件,操作完成后操作的状态显示为发送中,这时我们可以继续其他操作。等邮件群发完毕后,操作的状态自动改为已发送。
onWorkerStop worker进程

此事件在worker进程正常终止时发生

 

  • $worker_id是一个从0-$worker_num之间的数字,表示这个Worker进程的ID
  • $worker_id和进程PID没有任何关系
  • 进程异常结束,如被强制kill、致命错误、core dump时无法执行onWorkerStop回调函数
onConnect worker进程有新的连接进入时,在worker进程中回调
onClose worker进程CP客户端连接关闭后,在worker进程中回调此函数
onReceive worker进程接收到数据时回调此函数,发生在worker进程中
onPacket worker进程接收到UDP数据包时回调此函数,发生在worker进程中
onFinish worker进程当worker进程投递的任务在task_worker中完成时,task进程会通过finish()方法将任务处理的结果发送给worker进程
onWorkerExit worker进程

仅在开启reload_async特性后有效。异步重启特性

 

  • Worker进程未退出,onWorkerExit会持续触发
  • onWorkerExit仅在Worker进程内触发,Task进程不执行onWorkerExit
onPipeMessage worker进程

当工作进程收到由 sendMessage 发送的管道消息时会触发事件

onTask Task进程在task_worker进程内被调用。worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务
onWorkerStart Task进程 此事件在Worker进程/Task进程启动时发生
onPipeMessage Task进程当工作进程收到由 sendMessage 发送的管道消息时会触发事件

请勿在onShutdown、onWorkerStop、中调用任何异步协程相关API,触发onShutdown时底层已销毁了所有事件循环设施。

如上的表格就是 swoole 的进程可以绑定的时间, 并不是所有的;比如在启动的时候做的操作,那么就会触发启动的事件,发送信息的时候会触发的事件;
swoole 对于不同的进程,在不同的情况下就定义了不同的事件,这里可以像大家介绍一下事件的使用与其效果,但是并不是所有的事件。
我们可以看一下 swoole 在官方所提供的 swoole 运行流程图
 

 

1. 服务器关闭程序终止时最后一次事件是 onShutdown
2. 服务器启动成功后, onStart/onManagerStart/onWorkerStart 会在不同的进程内并发执 行,并不是顺序的。
3. 所有事件回调均在 $server->start 后发生, start 之后写的代码是无效代码。
4. onStart/onManagerStart/onWorkerStart 3 个事件的执行顺序是不确定的
 
Swoole Reactor Worker TaskWorker 之间可以紧密的结合起来,提供更高级的使用方式。
 
一个更通俗的比喻,假设 Server 就是一个工厂,那 Reactor 就是销售,接受客户订单。而 Worker 就是工人,当销售接到订单后, Worker 去工作生产出客户要的东西。而 TaskWorker 可以理解为行政人员,可以帮助 Worker
些杂事,让 Worker 专心工作。

 

我们可以尝试对于 swoole 的进程更名称
// 1. 创建swoole 默认创建的是一个同步的阻塞tcp服务
$host = "0.0.0.0"; // 0.0.0.0 代表接听所有
$post = 9500;

$serv = new Swoole\Server($host, $post);

// 2. 注册事件
$serv->on('Start', function(){
    // sleep(1); // 这个函数不推荐在swoole中直接使用
    swoole_set_process_name("swoole:start ");
    // 修改进程的名称
    echo "=== >>> on start \n";
});
$serv->on('managerStart', function(){
    swoole_set_process_name("swoole:managerStart ");
    // 修改进程的名称
    echo "=== >>> on workerStart \n";
});
$serv->on('workerStart', function(){
    swoole_set_process_name("swoole:workerStart ");
    // 修改进程的名称
    echo "=== >>> on workerStart \n";
});

//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) {
    echo "Client: Connect.\n";
});

$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
      $serv->send($fd, "Server: ");
});

//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
    echo "QQ离线.\n";
});

$serv->start(); // 阻塞与非阻塞

效果:

 

多看看 swoole 手册中的高级部分,因为对于 swoole 的理解会更加好一点
swoole 中的 Reactor https://wiki.swoole.com/wiki/page/163.html
1. Reactor 是管理 tcp 连接的, 并向 worker 进程投递请求,投递方式根据 dispatch_mode 配置。
2. worker 进程可以自己处理任务,也可以投递给 taskworker 进程来做。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值