ホームページ  >  記事  >  PHPフレームワーク  >  Workermanソースコード解析の起動手順を詳しく解説

Workermanソースコード解析の起動手順を詳しく解説

尚
転載
2019-11-25 13:57:133580ブラウズ

次のコラム workerman チュートリアル では、workerman のソース コード解析の起動プロセスを紹介します。

Workermanソースコード解析の起動手順を詳しく解説

#労働者

バージョン: 3.1.8 (linux)

モデル: GatewayWorker (Worker モデルと比較できます)

注: 説明するコードの一部のみを掲載し、ソースを示します

#workerman は当初 Linux バージョンのみを開発していましたが、後に win が追加され、コマンド ライン モード (cli) に基づいて実行されます。

マルチプロセス モデルワーカー プロセス、マスター、ゲートウェイ、およびワーカー、ゲートウェイは主に IO イベントの処理とクライアント接続ステータスの保存に使用されます。データ処理要求を Worker などのタスクに送信します Worker は完全なビジネス ロジック処理です 前者は IO 集約的で、後者はコンピューティング集約的です ネットワークを介して通信します ゲートウェイとワーカーはペアで通信アドレスを登録します分散導入に非常に便利で、業務処理量が多い場合にはWorkerサービスを追加するだけで済みます。

Workermanソースコード解析の起動手順を詳しく解説これらには、監視、子プロセスのステータスの監視、子プロセスへのシグナルの送信、ターミナルからのコマンドとシグナルの受け取りを担当する親プロセス (マスター) があります。 。親プロセスは、システム全体が起動した後の入り口となるプロセスと言えます。

コマンド解析の開始コマンド モード (cli) で実行されているため (Web からのリクエストを処理する fpm との違いに注意してください)ページ) には、起動スクリプト解析コマンドが必要です。たとえば、バージョン 3.x (以前のデフォルトはデーモン) では、デーモン プロセスが実行中であることを示す -d パラメータが追加されています。このパラメータに解析されるときは、self:: を設定します。 $daemon = true、その後 fork 子プロセスは、現在のプロセス グループから離脱したり、プロセス グループ リーダーを設定したりすることができます。

2 つの非常に重要なパラメーター $argc と $argc があります。前者はパラメーターの数を表し、後者はコマンドのすべてのパラメーターを保存する配列です (例: sudo php start.php start) -d、$argv は array([0]=>start.php, [1]=>start, [2]=>-d) で、$argv は主に解析に使用されます。

スタートアップは主に次の手順を実行します:

1. 自動ローダー Autoloader をインクルードし、各アプリケーションの下にスタートアップ ファイルをロードします;

2. _appInitPath ルート ディレクトリを設定します;

3. パラメータを解析し、初期化し、対応するコマンドを実行します。

次は特定の実装 (workerman/worker.php) です:

public static function parseCommand()
    {
        // 检查运行命令的参数
        global $argv;
        $start_file = $argv[0]; 

        // 命令
        $command = trim($argv[1]);
        
        // 子命令,目前只支持-d
        $command2 = isset($argv[2]) ? $argv[2] : '';
        
        // 检查主进程是否在运行
        $master_pid = @file_get_contents(self::$pidFile);
        $master_is_alive = $master_pid && @posix_kill($master_pid, 0);
        if($master_is_alive)
        {
            if($command === 'start')
            {
                self::log("Workerman[$start_file] is running");
            }
        }
        elseif($command !== 'start' && $command !== 'restart')
        {
            self::log("Workerman[$start_file] not run");
        }
        
        // 根据命令做相应处理
        switch($command)
        {
            // 启动 workerman
            case 'start':
                if($command2 === '-d')
                {
                    Worker::$daemonize = true;
                }
                break;
            // 显示 workerman 运行状态
            case 'status':
                exit(0);
            // 重启 workerman
            case 'restart':
            // 停止 workeran
            case 'stop':
                // 想主进程发送SIGINT信号,主进程会向所有子进程发送SIGINT信号
                $master_pid && posix_kill($master_pid, SIGINT);
                // 如果 $timeout 秒后主进程没有退出则展示失败界面
                $timeout = 5;
                $start_time = time();
                while(1)
                {
                    // 检查主进程是否存活
                    $master_is_alive = $master_pid && posix_kill($master_pid, 0);
                    if($master_is_alive)
                    {
                        // 检查是否超过$timeout时间
                        if(time() - $start_time >= $timeout)
                        {
                            self::log("Workerman[$start_file] stop fail");
                            exit;
                        }
                        usleep(10000);
                        continue;
                    }
                    self::log("Workerman[$start_file] stop success");
                    // 是restart命令
                    if($command === 'stop')
                    {
                        exit(0);
                    }
                    // -d 说明是以守护进程的方式启动
                    if($command2 === '-d')
                    {
                        Worker::$daemonize = true;
                    }
                    break;
                }
                break;
            // 平滑重启 workerman
            case 'reload':
                exit;
        }
    }

ウォーカー コードのコメントは非常に詳細です。詳細は次のとおりです:

1. main process Survival: 17 行目の論理 AND 演算. メイン プロセス PID が存在する場合、シグナル 0 がプロセスに送信されます. 実際には、情報は送信されません. プロセス (またはプロセス グループ) が生存しているかどうかのみ検出します。現在のユーザーを検出します。システム信号を送信する権限がありますか?

2. メイン プロセスの PID が保存されるのはなぜですか?システム起動後は現在のターミナルから逃げ出す シャットダウンなどのコマンドを実行したい場合は、別プロセスでコマンドが実行される プロセスのPIDすら分からない場合、誰にシグナルを送ればよいのかに?

したがって、メイン プロセスの PID は保存する必要があり、メイン プロセスは他の子プロセスを監視する責任があるため、操作を続行するための入り口となります。

Worker::runAll()#php のソケット プログラミングは実際には C に似ています。後者はソケットを再ラップし、インターフェイスが PHP に提供され、PHP でのネットワーク プログラミングの手順が大幅に削減されます。

例: stream_socket_server と stream_socket_client はサーバー/クライアント ソケットを直接作成します (php には 2 セットのソケット操作関数があります)。 wm は前者を多用しており、起動プロセスは次のとおりです (コメントは非常に詳細です):

public static function runAll()
    {
        // 初始化环境变量
        self::init();
        // 解析命令
        self::parseCommand();
        // 尝试以守护进程模式运行
        self::daemonize();
        // 初始化所有worker实例,主要是监听端口
        self::initWorkers();
        //  初始化所有信号处理函数
        self::installSignal();
        // 保存主进程pid
        self::saveMasterPid();
        // 创建子进程(worker进程)并运行
        self::forkWorkers();
        // 展示启动界面
        self::displayUI();
        // 尝试重定向标准输入输出
        self::resetStd();
        // 监控所有子进程(worker进程)
        self::monitorWorkers();
    }

プロセスの重要なポイントについてお話しましょう:

1. 環境の初期化メインのプロセス名、ログ パス、初期化タイマーなどの設定などの変数;

2. 主に $argc と $argc を使用してコマンド ライン パラメーターを解析します。使用方法は C 言語と同じです。

##3. 現在のターミナルから脱却するために、デーモン プロセスを生成します (2 年前、ほとんどの人は PHP をデーモンとして使用できないと考えていました。実際、これは誤解です。実際、 Linux における PHP のプロセス モデルは非常に安定しています。現在、wm のビジネスへの応用は非常に成熟しています。ある国内企業は毎日数億件の接続を処理しています。注文や支払いの電話に使用されるため、心配を解消できます。);

4. すべてのワーカー インスタンスを初期化します (これはメイン プロセスで行われ、多数のサーバーが生成されるだけで、モニターはセットアップされないことに注意してください。詳細 プロセス モデルは子プロセスで監視しています。 、IO多重化);

5.メインプロセスの信号処理関数を登録;

6. メイン プロセスの PID を保存します。システムの実行中は、ターミナルでシステム ステータスを確認したり、シャットダウンまたは再起動コマンドを実行したりできます。通信はメイン プロセスを介して行われるため、メイン プロセスの PID を知る必要があります。ターミナルに 1 つを入力する必要があることがわかっています。実行可能コマンドは、実際には、実行のために現在のターミナルの下に新しいサブプロセスを作成します。そのため、メイン プロセスの PID を知って、SIGNAL を WM メイン プロセスに送信する必要があります。このとき、シグナルは処理関数は信号をキャプチャし、コールバックを通じて実行します。

7. 子プロセスを作成し、現在のプロセス ユーザー (root) を設定します。マルチプロセスモデルでは、2 種類のサブプロセスがそれぞれ異なるサーバーアドレスをリッスンしますが、メインプロセスではサーバーを作成するだけで、リッスンの設定や指定された数のサーバーの生成は行いません。

理由は、プロセス内で同じソケットを複数回作成するとエラーが報告されるためです。ワーカーの数は実際にはソケットの数、つまりソケットの子プロセスの数です。子プロセスは親プロセスのコンテキストを継承しますが、特定のソケット イベントのみをリッスンします;

8. 子プロセスでは、サーバー ソケットを登録してイベントをリッスンし、拡張イベントを使用して IO の再利用を実現します。データ読み取りコールバック、およびソケット接続の登録 イベント コールバック;

9. 入力および出力リダイレクト;

10. メイン プロセスはサブプロセスのステータスを監視し、pcntl_signal_dispatch( ) 無限ループ内の関数で、サブプロセスの終了ステータスをキャプチャします。この関数は、子プロセスが終了するまでブロックされます;

ワーカーマン関連の詳細については、ワーカーマン チュートリアル#を参照してください。 ## カラム。

以上がWorkermanソースコード解析の起動手順を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。