05.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

Swoole想要实现最好的性能必须创建出多个工作进程帮助处理任务,但Worker进程就必须fork操作,但是fork操作是不安全的,如果没有管理会出现很多的僵尸进程,进而影响服务器性能,同时worker进程被误杀或者由于程序的原因会异常退出,为了保证服务的稳定性,需要重新创建worker进程。

Swoole在运行中会创建一个单独的管理进程,所有的worker进程和task进程都是从管理进程Fork出来的。管理进程会监视所有子进程的退出事件,当worker进程发生致命错误或者运行生命周期结束时,管理进程会回收
此进程,并创建新的进程。换句话也就是说,对于worker、task进程的创建、回收等操作全权有“保姆”Manager进程进行管理。

再来一张图梳理下Manager进程和Worker/Task进程的关系图

1.3 worker
worker 进程属于swoole的主逻辑进程,用户处理客户端的一系列请求,接受由Reactor线程投递的请求数据包,并执行PHP回调函数处理数据生成响应数据并发给Reactor线程,由Reactor线程发送给TCP客户端可以是异步非阻塞模式,也可以是同步阻塞模式。

1.4 task
taskWorker进程这一进程是swoole提供的异步工作进程,这些进程主要用于处理一些耗时较长的同步任务,在worker进程当中投递过来。

2.进程查看及流程梳理

当启动一个Swoole应用时,一共会创建2 + n + m个进程,2为一个Master进程和一个Manager进程,其中n为Worker进程数。m为TaskWorker进程数。

默认如果不设置,swoole底层会根据当前机器有多少CPU核数,启动对应数量的Reactor线程和Worker进程。我机器为2核的。Worker为2。

所以现在默认我启动了1个Master进程,1个Manager进程,和2个worker进程,TaskWorker没有设置也就是为0,当前server会产生4个进程。

在启动了server之后,在命令行查看当前产生的进程

[root@VM_0_10_centos ~]# pstree -ap | grep http_server
  |   |       `-php,14586 http_server_oop.php
  |   |           |-php,14587 http_server_oop.php
  |   |           |   |-php,14590 http_server_oop.php
  |   |           |   `-php,14591 http_server_oop.php
  |           |-grep,18614 --color=auto http_server
[root@VM_0_10_centos ~]# ps -aux | grep http_server
root     14586  0.0  1.5 591468 61836 pts/0    Sl+  11:36   0:00 php http_server_oop.php
root     14587  0.0  0.5 446000 21308 pts/0    S+   11:36   0:00 php http_server_oop.php
root     14590  0.0  0.5 447828 21604 pts/0    S+   11:36   0:00 php http_server_oop.php
root     14591  0.0  0.5 447828 21604 pts/0    S+   11:36   0:00 php http_server_oop.php
root     18658  0.0  0.0 112716   972 pts/1    S+   11:58   0:00 grep --color=auto http_server
[root@VM_0_10_centos ~]# 

这三个进程中,所有进程的根进程,也就是例子中的14586进程,就是所谓的Master进程;而14587进程,则是Manager进程;最后的14590和14591进程,是Worker进程。

当然我们也可以对于swoole的进程限制数量

<?php
// server
$server->set([
'worker_num'=>1, //设置进程
]);
?>

效果

[root@VM_0_10_centos ~]# ps -aux | grep http_server
root     11692  0.8  1.5 517320 61832 pts/0    Sl+  14:14   0:00 php http_server_oop.php
root     11693  0.0  0.5 445584 21308 pts/0    S+   14:14   0:00 php http_server_oop.php
root     11695  0.0  0.5 447828 21552 pts/0    S+   14:14   0:00 php http_server_oop.php
root     11714  0.0  0.0 112712   972 pts/1    S+   14:14   0:00 grep --color=auto http_server
[root@VM_0_10_centos ~]# pstree -ap | grep http_server
  |   |       `-php,11692 http_server_oop.php
  |   |           |-php,11693 http_server_oop.php
  |   |           |   `-php,11695 http_server_oop.php
  |           |-grep,11747 --color=auto http_server
[root@VM_0_10_centos ~]# 

3.swoole进程函数

事件那种类型的进程作用
onstartmaster进程server启动在主进程
onshutdownmaster进程此事件在server正常结束时发生
onManagerStartmanager进程当管理进程启动时调用它
onManagerStopmanager进程当管理进程结束时调用它
onWorkErrormanager进程当worker/task_worker进程发生异常后会在manager进程内回调此函数
onWorkerStartworker进程此事件在Worker进程/Task进程启动时发生
onWorkerStopworker进程此事件在worker进程终止时发生
onConnectworker进程有新的连接进入时,在worker进程中回调
onCloseworker进程TCP客户端连接关闭后,在worker进程中回调此函数
onReceiveworker进程接收到数据时回调此函数,发生在worker进程中
onPacketworker进程接收到UDP数据包时回调此函数,发生在worker进程中
onFinishworker进程当worker进程投递的任务在task_worker中完成时,task进程会通过finish()方法将任务处理的结果发送给worker进程
onWorkerExitworker进程仅在开启reload_async特性后有效。异步重启特性
onPipeMessageworker进程当工作进程收到由 sendMessage 发送的管道消息时会触发事件
onTaskTask进程在task_worker进程内被调用。worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务

如上的表格就是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的进程更名称

<?php
$host = "0.0.0.0";
$post = 9501;

//1.创建swoole
$serv = new Swoole\Server($host,$post);

$serv->set([
    'worker_num'=>1
]);

//2.注册事件
$serv->on('Start',function(){
    swoole_set_process_name("swoole:start");
    echo "=== >>> on Start \n";
});

$serv->on('managerStart',function(){
    swoole_set_process_name("swoole:managerStart");
    echo "=== >>> on managerStart \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();
[root@VM_0_10_centos 04]# php swoole_server.php
=== >>> on Start
=== >>> on managerStart
=== >>> on workerStart
[root@VM_0_10_centos ~]# ps -aux | grep swoole
root     26278  0.0  1.5 517192 61840 pts/0    Sl+  18:24   0:00 swoole:start
root     26279  0.0  0.5 445584 21732 pts/0    S+   18:24   0:00 swoole:managerStart
root     26281  0.0  0.5 447636 22116 pts/0    S+   18:24   0:00 swoole:workerStart
root     27906  0.0  0.0 112712   968 pts/1    S+   18:33   0:00 grep --color=auto swoole
[root@VM_0_10_centos ~]#

建议大家在平时的工作中可以看看swoole手册中的高级部分,因为对于swoole的理解会更加好一点
swoole中的Reactor https://wiki.swoole.com/wiki/page/163.html

  1. Reactor是管理tcp连接的, 并向worker进程投递请求,投递方式根据dispatch_mode配置。
  2. worker进程可以自己处理任务,也可以投递给taskworker进程来做。

王如棋博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论