Cet article vous apporte des exemples de code sur la gestion des processus PHP. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.
Cet article est un complément et une amélioration de l'article précédent. Créez un processus maître, installez une minuterie dans le processus maître, détectez la longueur de la file d'attente toutes les 5 minutes et calculez-la en fonction de la longueur de la file d'attente. . Le processus de travail requis,
puis créez ou tuez le processus enfant. L’avantage est d’éviter que la file d’attente ne s’accumule et que les tâches ne soient pas traitées à temps. Pour mettre à jour le code métier, seule l'opération de rechargement est requise.
L'ensemble du processus comporte les points de connaissance suivants :
Étapes pour créer un démon :
Paramètres Autorisations de fichier par défaut
fork un processus, le processus parent se termine
Appelez setsid pour créer une nouvelle session
Remplacez le répertoire de travail actuel par le répertoire racine
Fermer les descripteurs de fichiers qui ne sont plus nécessaires
Utiliser le minuteur d'implémentation du signal
Le minuteur de l'article précédent dépend des tâches planifiées du système. Cette fois, il est implémenté à l'aide du signal de réveil. Les versions inférieures à PHP 5.3.0 dépendent des ticks, 5.3. .0 et la version ci-dessus peuvent utiliser pcntl_signal_dispatch
Signal : fournit une méthode de traitement d'événement asynchrone lorsqu'un signal se produit, le processus dispose des trois manières suivantes pour traiter le signal
SIGINT( 2) : signal de fin de programme, généralement émis lorsque Ctrl-C), utilisé pour notifier au groupe de processus de premier plan de terminer le processus
SIGQUIT (3) : similaire à SIGINT, mais est signalé par QUIT caractère (généralement Ctrl+/) Contrôle. Lorsque le processus reçoit ce message et se termine, il génère un fichier principal
SIGKILL(9) : terminez le processus immédiatement et ne peut pas être ignoré ou bloqué
SIGUSR1(10) : Signal défini par l'utilisateur
SIGUSR2(12) : réservé aux utilisateurs
SIGALRM(14) : signal de réveil
SIGTERM(15) : terminer le processus et peuvent être capturés par le programme afin que le processus puisse être complété par des opérations de nettoyage.
SIGSTOP(19) : Arrêter un processus. Le processus n'est pas encore terminé. Il suspend simplement l'exécution
Déployez le code métier, le code principal est le suivant
Une chose à noter est que lors de la création d'un processus démon pour fermer les entrées et sorties, ainsi que le flux de sortie d'erreur, s'il y a un écho, etc. derrière les caractères de sortie du code, une erreur fatale se produira et le flux de sortie doit être redirigé vers /dev/null dans le code php. Ou rediriger lorsque le terminal démarre le processus
<?php define('PROC_MAX', 10); define('PROC_MIN', 5); $cmd = $argv[1]; $aPid = []; $pidFile = __DIR__ . '/pid.pid'; $pid = file_get_contents($pidFile); switch($cmd){ case 'start' : if(posix_kill($pid, 0)){ echo "gamelog process is already exsits!\n"; return false; } //设置默认文件权限 umask(022); //fork $pid = pcntl_fork(); if($pid < 0){ exit('fork error!'); }else if($pid > 0){ exit; } //脱离当前终端 posix_setsid(); //将当前工作目录更改为根目录 chdir('/'); //关闭文件描述符 fclose(STDIN); fclose(STDOUT); fclose(STDERR); //重定向输入输出 global $STDOUT, $STDERR; $STDOUT = fopen('/dev/null', 'a'); $STDERR = fopen('/dev/null', 'a'); cli_set_process_title('gamelog:master'); $pid = posix_getpid(); file_put_contents($pidFile, $pid); //闹钟信号 pcntl_signal(SIGALRM, function() use (&$aPid) { pcntl_alarm(300); $workerNum = mt_rand(1, 20);//此处检测你需要的进程数 $daemonNum = count($aPid); ($workerNum > PROC_MAX) && ($workerNum = PROC_MAX); if($daemonNum < $workerNum){ $procNum = $workerNum - $daemonNum; $procNum = max(PROC_MIN, $procNum); for($p = 1; $p <= $procNum; $p++){ $pid = pcntl_fork(); if ($pid < 0) { exit('fork error!'); } else if ($pid == 0) { cli_set_process_title('gamelog:worker'); while (true) { //do your work usleep(100); } exit(); } else { $aPid[] = $pid; } } }else if($daemonNum > $workerNum){ $wokerNum = max($wokerNum, PROC_MIN); $killNum = $daemonNum - $workerNum; foreach($aPid as $key=>$pid){ if(posix_kill($pid, SIGKILL)){ unset($aPid[$key]); if(--$killNum <= 0){ break; } } } } }, false); pcntl_signal(SIGUSR1, function() use (&$aPid, $pid){ foreach($aPid as $key=>$chpid){ if(!posix_kill($chpid, SIGKILL)){ echo "kill child $chpid faild\n"; } } posix_kill($pid, SIGKILL); }, false); pcntl_signal(SIGUSR2, function() use (&$aPid, $pid){ foreach($aPid as $key=>$chpid){ if(!posix_kill($chpid, SIGKILL)){ echo "kill child $chpid faild\n"; } } if(!posix_kill($pid, SIGALRM)){ echo "restart gamelog faild\n"; } }, false); posix_kill($pid, SIGALRM); while (true) { pcntl_signal_dispatch(); $pid = pcntl_wait($status, WUNTRACED);//不阻塞 } break; case 'stop' : if(!posix_kill($pid, SIGUSR1)){ exit('stop gamelog process error!'); } break; case 'reload' : if(!posix_kill($pid, SIGUSR2)){ exit('restop gamelog process error!'); } break; default : echo "Useage php signal.php start|stop|reload\n"; }
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!