私たちが最初にサーバーの記事に出会ったとき、swoole はイベント駆動型であると言いました。 swoole を使用する過程で、swoole の使用は非常に簡単で、ビジネス ロジックを処理するために対応するコールバックを登録するだけでよいことにも気づきました。
ただし、swoole の学習を続ける前に、swoole の操作プロセスとプロセス モデルをもう一度見てみる必要があります。
推奨事項 (無料): swoole
最初の 2 つの記事でサーバーとタスクについて簡単に紹介しました。サーバーについては後ほど説明します。特に指定がない限り、スクリプトの作成と実行はすべて CLI で実行されるため、詳細は説明しません。
ここで、分析する単純なサーバーを作成します。ファイルの名前は、server-process.php
$serv = new swoole_server('127.0.0.1', 9501); $serv->set([ 'worker_num' => 2, 'task_worker_num' => 1, ]); $serv->on('Connect', function ($serv, $fd) { }); $serv->on('Receive', function ($serv, $fd, $fromId, $data) { }); $serv->on('Close', function ($serv, $fd) { }); $serv->on('Task', function ($serv, $taskId, $fromId, $data) { }); $serv->on('Finish', function ($serv, $taskId, $data) { }); $serv->start();
ここでは、2 つのワーカー プロセスと 1 つのタスク プロセスを選択していることに注意してください。このサーバーを作成すると3つのプロセスが開始されるということでしょうか?見てみましょう
新しいターミナルを開いて、ps コマンドを使用して結果を確認してみましょう
$ ps aux | grep server-process root 21843 xxx... php server-process.php root 21844 xxx... php server-process.php root 21846 xxx... php server-process.php root 21847 xxx... php server-process.php root 21848 xxx... php server-process.php root 21854 xxx... grep --color=auto server-process
読みやすいように、ps 結果内の重要でないデータの一部がわずかに処理されています。
最後の結果 (最後に実行した ps コマンド) を除くと、同様のプロセスが 5 つも実行されていることがわかりました。私たちの理解によれば、3 つあるはずではありませんか? なぜ存在するのでしょうか?あと2つどれですか?
「プロセス/スレッド」の記事で説明したマルチプロセスの実装を覚えていますか?マルチプロセスの実装について話すとき、マスター-ワーカー モードが一般的に設計されています。nginx の一般的なデフォルトのマルチプロセス モードもまったく同じです。もちろん、swoole のデフォルトのマルチプロセス モデルもマルチプロセスです。プロセスモデル。
マスター-ワーカー モデルと比較すると、swoole のプロセス モデルはマスター-マネージャー-ワーカーとして説明できます。つまり、Master-Worker に基づいて Manager プロセスの追加レイヤーが追加されます。これは、最初に提起した質問、つまりなぜ 3 つのプロセスではなく 5 つのプロセスがあるのかという質問にも答えます。 (1 マスタープロセス、1 マネージャープロセス、2 ワーカープロセス、1 タスクプロセス)
「存在には合理性がある」という言葉があるように、マスター\マネージャー\ の 3 つのプロセスが存在する理由を見てみましょう。労働者は存在する。
マスター プロセスはマルチスレッド プログラムです。注: これまでの理解によれば、複数のスレッドは 1 つのプロセスのコンテキストで実行されます。実際、1 つのプロセス内の各スレッドは独自のコンテキストを持ちますが、同じプロセス内に共存するため、それも共有します。このプロセスは、そのコード、データなどを含みます。
戻ってマスター プロセスについて話を続けましょう。マスター プロセスは私たちのメイン プロセスであり、生と死の力を担当します。マスター プロセスが終了すると、その下にあるものはすべて完了する必要があります。メイン スレッド、複数の Reactor スレッドなどを含むマスター プロセス。
各スレッドには独自の目的があります。たとえば、メイン スレッドは Accept、信号処理、その他の操作に使用され、Reactor スレッドは TCP 接続の処理、ネットワーク IO の処理、および送受信を行うスレッドです。データ。
注意すべき 2 つの点:
通常、メインスレッドは新しい接続を処理した後、その接続を固定の Reactor スレッドに割り当てます。そして、この Reactor スレッドは常にこのソケットの監視を担当します (ソケットは上記の後半で説明します)。ソケット (別のプロセスとのネットワーク間通信に使用されるファイルです。ファイルは読み書きできます) に更新されます。つまり、ソケットが読み取り可能な場合、データが読み取られ、リクエストが処理されます。これはワーカー プロセスに割り当てられており、最初に導入したときのワーカー プロセスのコールバック onReceive の 3 番目のパラメーター $fromId の意味も説明しています。ソケットが書き込み可能になると、データは TCP クライアントに送信されます。
画像を使用して明確に整理してください
では、なぜ swoole は Nginx のようなマスター ワーカー プロセス構造を持たないのでしょうか? Manager プロセスは何をするのでしょうか?
私はこれを言おうとしていました。
マスター-ワーカー モデルでは、マスターは 1 つだけ存在し、ワーカーは親プロセスのマスター プロセスからコピーされ、複数のワーカー プロセスが存在できることがわかっています。
注: Linux では、親プロセスは fork 関数を呼び出すことで新しい子プロセスを作成できます。子プロセスは親プロセスのコピーであり、ほぼ同じではありますが、まったく同じではありません。この 2 つの最大の違いは、それは、両方とも独自の独立したプロセス ID、つまり PID を持っているということです。
マルチスレッドのマスター プロセスの場合、複数のワーカー プロセスが必要な場合は、操作をフォークする必要がありますが、フォーク操作は安全ではありません。そのため、swoole にはフルタイムのマネージャー プロセスがあります。 Manager プロセスは、フォークの操作とワーカー/タスク プロセスの管理を担当する専用のプロセスです。言い換えれば、「ナニー」マネージャー プロセスは、ワーカー プロセスの作成、リサイクル、その他の操作を管理する完全な権限を持ちます。
通常,worker进程被误杀或者由于程序的原因会异常退出,Manager进程为了保证服务的稳定性,会重新拉起新的worker进程,意思就是Worker进程你发生意外“死”了,没关系,我自身不“死”,就可以fork千千万万个你。
当然,Master进程和Manager进程我们是不怎么关心的,从前面两篇文章我们了解到,真正实现业务逻辑,是在worker/task进程内完成的。
再来一张图梳理下Manager进程和Worker/Task进程的关系。
再回到我们开篇抛出的的5个进程的问题,ps的结果简直一模一样,有没有办法能区分这5个进程哪个是哪个呢?
有同学要说啦,既然各个进程之间存在父子关系,那我们就可以通过linux的pstree命令查看结果。
$ pstree | grep server-process | | \-+= 02548 manks php server-process.php | | \-+- 02549 manks php server-process.php | | |--- 02550 manks php server-process.php | | |--- 02551 manks php server-process.php | | \--- 02552 manks php server-process.php | \--- 02572 manks grep server-process
注:centos下命令可修改为 pstree -ap | grep server-process
从结果中我们可以看出,进程id等于02548的进程就是Master进程,因为从结构上看就它是“父”嘛,02549是Manager进程,Worker进程和Task进程就是02550、02551和02552了(每个人的电脑上显示的进程id可能不同,但顺序是一致的,依照此模型分析即可)。
我们看到pstree命令也只能得到大致结果,而且在事先不知道的情况下,根本无法区分Worker进程和Task进程。
在swoole中,我们可以在各个进程启动和关闭的回调中去解决上面这个问题。各个进程的启动和关闭?那岂不是又要记住主进程、Manager进程、Worker进程,二三得六,6个回调函数?
是的,不过这6个是最简单也是最好记的,你实际需要了解的可能还要更多。
Master进程: 启动:onStart 关闭:onShutdown Manager进程: 启动:onManagerStart 关闭:onManagerStop Worker进程: 启动:onWorkerStart 关闭:onWorkerStop
提醒:task_worker也会触发onWorkerStart回调。
是不是很好记?那我们就在server-process.php中通过上面这几种回调来实现对各个进程名的修改。
$serv->on("start", function ($serv){ swoole_set_process_name('server-process: master'); }); // 以下回调发生在Manager进程 $serv->on('ManagerStart', function ($serv){ swoole_set_process_name('server-process: manager'); }); $serv->on('WorkerStart', function ($serv, $workerId){ if($workerId >= $serv->setting['worker_num']) { swoole_set_process_name("server-process: task"); } else { swoole_set_process_name("server-process: worker"); } });
注意:因mac下不支持swoole_set_process_name函数,即不能修改进程名,我们换台centos运行下看看结果(实际上你的服务器也不可能是mac)
# ps aux | grep server-process root 27546 xxx... server-process: master root 27547 xxx... server-process: manager root 27549 xxx... server-process: task worker root 27550 xxx... server-process: worker root 27551 xxx... server-process: worker root 27570 xxx... grep --color=auto simple
运行结果谁是谁一目了然,简直了!
有同学傻眼了,说在workerStart回调中写的看不明白,worker进程和task进程怎么区分的?
我来解释一下:在onWorkerStart回调中,$workerId表示的是一个值,这个值的范围是0~worker_num,worker_num是我们的对worker进程的配置,其中0~worker_num表示worker进程的标识,包括0但不包括worker_num;worker_num~worker_num+task_worker_num是task进程的标识,包括worker_num不包括worker_num+task_worker_num。
按照高中学的区间的知识可能更好理解,以我们案例的配置,workerId的值的范围就是[0,2],[0,2)表示worker进程,[2,3)就表示task_worker进程。
swoole的进程模型很重要,本篇掌握不好,后面的理解可能就会有些问题。
我们在onWorkerStart的回调中,用了serv−>setting去获取配置的server信息,在swoole中预留了一些swooleserver的属性,我们可以在回调函数中访问。比如说我们可以用serv−>setting去获取配置的server信息,在swoole中预留了一些swooleserver的属性,我们可以在回调函数中访问。比如说我们可以用serv->connections属性获取当前server的所有的连接,再比如我们可以通过$serv->master_pid属性获取当前server的主进程id等等。
以上がスウールのプロセスモデルの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。