Maison > cadre php > Workerman > Explication détaillée du processus de démarrage de l'analyse du code source Workmanman

Explication détaillée du processus de démarrage de l'analyse du code source Workmanman

Libérer: 2019-11-26 14:26:33
avant
3818 Les gens l'ont consulté

La colonne suivante présentera le processus de démarrage de l'analyse du code source Workerman à partir de la colonne Tutoriel Workerman J'espère que cela sera utile aux amis dans le besoin !

Explication détaillée du processus de démarrage de l'analyse du code source Workmanman

ouvrier

Version : 3.1.8 (linux)

Modèle : GatewayWorker (le modèle Worker peut lui être comparé)

Remarque : Seule la partie explication du code est publiée, et la source est donné sous la forme d'un nom de fichier. Vous pouvez le vérifier par vous-même

Workerman n'a initialement développé que la version Linux, win a été ajouté plus tard et il s'exécute en mode ligne de commande (cli).

Modèle multi-processus

Le processus de travail, le maître, la passerelle et la passerelle de travail sont principalement utilisés pour traiter les événements IO et enregistrer l'état du lien client. .Envoyer des requêtes de traitement de données à Worker et à d'autres tâches. Worker est un traitement de logique métier complet. Le premier nécessite beaucoup d'E/S et le second nécessite beaucoup de calcul. Ils communiquent via le réseau et Worker enregistrent les adresses de communication par paires. est très pratique pour un déploiement distribué. Si le volume de traitement métier est important, vous pouvez simplement ajouter des services Worker.

Explication détaillée du processus de démarrage de lanalyse du code source Workmanman

Ils ont un processus parent (Maître) chargé de surveiller, de surveiller l'état du processus enfant, d'envoyer des signaux au processus enfant et d'accepter les commandes et les signaux du terminal . Le processus parent peut être considéré comme le point d'entrée après le démarrage de l'ensemble du système.

Démarrer l'analyse des commandes

Comme il fonctionne en mode commande (cli) (notez la différence avec fpm, ce dernier gère les requêtes du page Web), il doit y avoir une commande d'analyse du script de démarrage. Par exemple, la version 3.x (auparavant, la valeur par défaut était démon) ajoute un paramètre -d pour indiquer que le processus démon est en cours d'exécution. Lors de l'analyse de ce paramètre, définissez self : :$daemon = true, puis fork Le processus enfant peut quitter le groupe de processus actuel, définir le chef du groupe de processus, etc.

Il y a deux paramètres très importants $argc et $argc Le premier représente le nombre de paramètres, et le second est un tableau qui enregistre tous les paramètres de la commande, tel que : sudo php start.php start. -d, $argv est un tableau([0]=>start.php, [1]=>start, [2]=>-d), et l'analyse utilise principalement $argv.

Le démarrage effectue principalement les étapes suivantes :

1. Contient le chargeur automatique Autoloader pour charger les fichiers de démarrage sous chaque application

2. Définissez le répertoire racine _appInitPath ; 🎜>

3. Analysez, initialisez les paramètres et exécutez les commandes correspondantes.

Ce qui suit est l'implémentation spécifique (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;
        }
    }
Copier après la connexion

Les commentaires du code du marcheur sont très détaillés :

1. Survie du processus principal : opération ET logique à la ligne 17. Si le PID du processus principal existe, le signal 0 est envoyé au processus. En fait, aucune information n'est envoyée. Il détecte uniquement si le processus (ou le groupe de processus) est vivant, et également. détecte l'utilisateur actuel. Avez-vous l'autorisation d'envoyer des signaux système ?

2. Pourquoi le PID du processus principal est-il enregistré ? Une fois le système démarré, il s'éloigne du terminal actuel. Si vous souhaitez exécuter des commandes d'arrêt ou d'autres commandes, la commande sera exécutée dans un autre processus. Si nous ne connaissons même pas le PID du processus, alors à qui devons-nous envoyer le signal. à?

Le PID du processus principal doit donc être enregistré, et le processus principal est responsable de la surveillance des autres processus enfants, c'est donc le point d'entrée pour nous pour continuer les opérations.

Worker::runAll()

La programmation du socket de PHP est en fait similaire au C. Ce dernier reconditionne le socket et fournit L'interface est fournie vers PHP, et les étapes de programmation réseau sous PHP sont grandement réduites.

Par exemple : stream_socket_server et stream_socket_client créent directement un socket serveur/client (php a deux ensembles de fonctions d'opération de socket). wm utilise largement le premier, et le processus de démarrage est le suivant (les commentaires sont très détaillés) :

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();
    }
Copier après la connexion

Parlons simplement des points clés du processus :

1. variables d'environnement, telles que la définition du nom du processus principal, du chemin du journal, du minuteur d'initialisation, etc. ;

2. Analyser les paramètres de ligne de commande, principalement en utilisant $argc et $argc.

3. Générer un processus démon, Afin de rompre avec le terminal actuel (il y a deux ans, la plupart des gens pensaient que PHP ne pouvait pas être utilisé comme démon. En fait, c'est un malentendu ! En fait, le modèle de processus de PHP sous Linux est très stable. Maintenant, l'application de wm dans les entreprises est très mature. Une entreprise nationale gère des centaines de millions de connexions chaque jour, utilisées pour les appels de commande et de paiement, vous pouvez mettre vos soucis de côté). ;

4. Initialisez toutes les instances de travail (notez que cela se fait dans le processus principal, cela génère simplement un tas de serveurs et ne configure pas de moniteurs. Plus Le modèle de processus surveille dans le processus enfant, cela c'est-à-dire le multiplexage IO);

5. Enregistrez la fonction de traitement du signal pour le processus principal ;

6. Enregistrez le PID du processus principal. Lorsque le système est en cours d'exécution, nous pouvons vérifier l'état du système dans le terminal ou exécuter des commandes d'arrêt ou de redémarrage. La communication se fait via le processus principal, nous devons donc connaître le PID du processus principal. Nous savons qu'il faut en taper un dans le terminal. La commande exécutable crée en fait un nouveau sous-processus sous le terminal actuel pour l'exécution, nous devons donc connaître le PID du processus principal pour envoyer SIGNAL au processus principal WM à ce moment-là. La fonction de traitement capture le signal et l'exécute via un rappel.

7. Créez un processus enfant et définissez l'utilisateur du processus actuel (root). Dans le modèle multi-processus, deux types de sous-processus écoutent respectivement différentes adresses de serveur. Dans le processus principal, nous créons uniquement des serveurs et ne configurons pas l'écoute, et nous ne générons pas non plus un nombre spécifié de serveurs.

La raison est que si nous créons le même socket plusieurs fois dans un processus, une erreur sera signalée. Le nombre de travailleurs est en fait le nombre de sockets, c'est-à-dire le nombre de processus enfants du socket. .Le processus enfant hérite du contexte du processus parent, mais n'écoute que les événements de socket spécifiques ;

8 Dans le processus enfant, enregistrez le socket du serveur pour écouter les événements et utilisez un événement étendu pour réaliser la réutilisation des E/S, enregistrez-vous. rappels de lecture de données, et également enregistrer les connexions de socket ;

9. Redirection d'entrée et de sortie

10. ) fonctionne dans une boucle infinie pour capturer l'état de sortie du sous-processus. Cette fonction se bloquera jusqu'à ce qu'un processus enfant se termine

Pour plus de connaissances sur Workerman, veuillez prêter attention au tutoriel Workerman colonne.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal