Maison  >  Article  >  développement back-end  >  Comment implémenter la gestion des événements d'initialisation de projet personnalisé Swoole (code)

Comment implémenter la gestion des événements d'initialisation de projet personnalisé Swoole (code)

不言
不言original
2018-09-13 17:01:151807parcourir

Le contenu de cet article explique comment implémenter le traitement des événements d'initialisation de projet personnalisé Swoole (code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Récemment, en utilisant le framework imi développé sur la base de Swoole pour développer un projet, j'ai rencontré une exigence, qui est d'effectuer un traitement d'initialisation du projet. Vous ne voulez pas que Swoole traite la demande avant la fin du processus d'initialisation. Étant donné que certaines valeurs peuvent ne pas être chargées, il existe un risque élevé de problèmes lors du traitement de la demande.

Le processus de réflexion et le code de démonstration pour résoudre le problème sont donnés ci-dessous.

Tout d'abord, après analyse, Swoole fonctionne en mode multi-processus et est divisé en processus Master, Manager et Worker.

Le processus Master est le processus dans lequel se trouve le fichier de commande cli qui démarre le service. Il y a un problème avec l'initialisation ici. Toutes les classes chargées et les variables globales peuvent être utilisées dans d'autres processus Worker et ne peuvent pas être chaudes. redémarré pour prendre effet.

La situation du processus Manager est fondamentalement la même que ci-dessus.

Ensuite, seul le processus Worker effectue le traitement, mais s'il est écrit dans l'événement WorkerStart, chaque processus Worker l'exécutera.

Définition de l'événement WorkerStart :

function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id est un nombre compris entre 0 et $worker_num, indiquant l'ID de ce processus Worker

Ensuite, c'est facile à gérer, déterminez directement le workerid comme 0 pour déclencher l'événement d'initialisation du projet. La question restante est de savoir comment empêcher tous les processus Worker de traiter les demandes jusqu'à ce que l'exécution de l'initialisation soit terminée.

J'y ai réfléchi et essayé. Ce problème peut être résolu en suspendant la coroutine. Le code de démonstration est le suivant :

<?php

use Swoole\Coroutine;

$http = new swoole_http_server(&#39;127.0.0.1&#39;, 8080);

$http->on(&#39;WorkerStart&#39;, function(swoole_http_server $server, $workerId){
    $initFlagFile = __DIR__ . &#39;/init.flag&#39;;
    if(0 === $server->worker_id && (!is_file($initFlagFile) || file_get_contents($initFlagFile) != $server->manager_pid))
    {
        // 处理项目初始化事件
        initApp();
        // 写入文件,保证不再重复触发项目初始化事件
        file_put_contents($initFlagFile, $server->manager_pid);
        // 当前worker进程恢复协程
        resumeCos();
        // 通知其它worker进程
        for($i = 1; $i < $server->setting[&#39;worker_num&#39;]; ++$i)
        {
            $server->sendMessage(&#39;init&#39;, $i);
        }
    }
});

$http->on(&#39;PipeMessage&#39;, function(swoole_http_server $server, $srcWorkerId, $data) {
    if(0 === $srcWorkerId && &#39;init&#39; === $data && !defined(&#39;APP_INITED&#39;))
    {
        // 其它worker进程恢复协程
        resumeCos();
    }
});

$http->on(&#39;request&#39;, function (swoole_http_request $request, swoole_http_response $response) {
    // 判断未初始化完毕,则挂起协程
    if(!defined(&#39;APP_INITED&#39;))
    {
        $GLOBALS[&#39;WORKER_START_END_RESUME_COIDS&#39;][] = Coroutine::getuid();
        Coroutine::suspend();
    }
    $response->header(&#39;content-type&#39;, &#39;text/html;charset=utf-8&#39;);
    $response->end(&#39;IMI 是一款基于 Swoole 开发的协程 PHP 开发框架,拥有常驻内存、协程异步非阻塞IO等优点。官方网站:<a href="https://imiphp.com" target="_blank">https://imiphp.com</a>&#39;);
});

$http->start();

/**
 * 处理项目初始化事件,比如这里延时5秒,模拟初始化处理
 *
 * @return void
 */
function initApp()
{
    $count = 5;
    for($i = 0; $i < $count; ++$i)
    {
        echo &#39;initing &#39;, ($i + 1), &#39;/&#39;, $count, PHP_EOL;
        sleep(1);
    }
}

/**
 * 恢复协程
 *
 * @return void
 */
function resumeCos()
{
    define(&#39;APP_INITED&#39;, true);
    $coids = $GLOBALS[&#39;WORKER_START_END_RESUME_COIDS&#39;] ?? [];
    fwrite(STDOUT, &#39;suspend co count: &#39; . count($coids) . PHP_EOL);
    foreach($coids as $id)
    {
        Coroutine::resume($id);
    }
}

En jugeant si l'initialisation est terminée dans la requête. événement, sinon, suspendez ensuite la coroutine actuelle et ajoutez l'ID de coroutine à la variable globale.

Lorsque le 0ème processus de travail termine l'initialisation, il réveille les coroutines suspendues en envoyant des messages aux autres processus de travail. Les requêtes arrivées pendant la période d'initialisation seront exécutées à ce moment-là.

Recommandations associées :

Explication détaillée de l'implémentation javascript des compétences events_javascript personnalisées

Comment utiliser les instructions personnalisées Angularjs dans le projet Utiliser

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!

Déclaration:
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