Close search
Hoa

Hack book de Hoa\Worker

Les workers permettent de décharger une application de tâches lourdes ou bloquantes. La bibliothèque Hoa\Worker permet de créer et de manipuler des workers à moindre effort.

Table des matières

  1. Introduction
  2. Worker partagé
    1. Où sont stockés les profils wid ?
  3. Communiquer avec un worker
  4. Utiliser les commandes dédiées
  5. Conclusion

Introduction

Il est conseillé de lire le chapitre sur Hoa\Zombie dans lequel nous apprennons comment transformer un processus en zombie. C'est l'idée qu'exploite Hoa\Worker pour, une fois le zombie créé, mettre en place un serveur qui va recevoir des messages. À chaque message reçu, un événement va être émis que nous pourrons intercepter pour exécuter une tâche.

Ces tâches peuvent être de plusieurs natures comme envoyer une notification (par exemple par mail), faire des opérations importantes sur des bases de données, traiter de multiples fichiers etc. L'idée est de décharger l'application de tâches qui pourraient la ralentir et s'exécuter en parallèle sans interférer avec l'exécution de l'application.

Même si le protocole établi permet une certaine intégrité et sûreté des messages, il est préférables que les communications se déroulent de serveur à serveur et non pas transitées par le client.

Hoa\Worker se présente en deux parties :

Worker partagé

Un worker est avant tout identifié par un workerId, parfois abrégé wid. Cet identifiant permet de créer un profil pour notre worker grâce à Hoa\Worker\Run qui ne s'occupe que de ça. Seul un identifiant et l'adresse du serveur créé dans le worker sont nécessaires pour établir un profil. Ensuite, nous pourrons démarrer un worker uniquement à partir de son identifiant.

La première étape va donc être de vérifier que le profil existe grâce à la méthode Hoa\Worker\Run::widExists, dans le cas contraire nous allons le créer avec la méthode Hoa\Worker\Run::register. Ainsi :

if (false === Hoa\Worker\Run::widExists('demorker')) {
    Hoa\Worker\Run::register('demorker', 'tcp://127.0.0.1:123456');
}

Nous sommes maintenant certains que le profil existe. Nous pouvons alors démarrer notre worker. Pour cela, nous devons utiliser son identifiant et son mot de passe (nécessaire pour l'arrêter) dans le constructeur de Hoa\Worker\Backend\Shared. Une fois l'objet créé, il émettra une seule catégorie d'événement : message, que nous allons écouter pour mettre en place notre propre protocole de traitement de tâches. Enfin, la méthode Hoa\Worker\Backend\Shared::run permet de démarrer le worker :

$file   = new Hoa\File\Write(__DIR__ . DS . 'Log');
$worker = new Hoa\Worker\Backend\Shared('demorker', 'iamapassword');
$worker->on('message', function (Hoa\Event\Bucket $bucket) use ($file) {
    // compute messages.
    $data = $bucket->getData();
    $file->writeAll($data['message'] . "\n");
});
$worker->run();

Nous sommes libres de faire ce que nous voulons pour traiter la tâche ! Le format est totalement libre : binaire, compressé, ligne de commande, objet sérialisé… nous pouvons envoyer ce que nous voulons.

Où sont stockés les profils wid ?

Les profils des workers sont stockés dans les fichiers hoa://Data/Variable/Run/workerId.wid. Attention à vérifier que ce chemin est bien défini, par exemple en choisissant le dossier /path/to/wid/directory :

$protocol = Hoa\Protocol\Protocol::getInstance();
$protocol['Data']['Variable']['Run']->setReach("\r" .  '/path/to/wid/directory);
var_dump(resolve('hoa://Data/Variable/Run'));

/**
 * Will output:
 *     string(21) "/path/to/wid/directory
 */

Notons que si nous utilisons Hoa avec son dossier Data/ alors hoa://Data/ se définira automatiquement vers ce dossier et nous n'aurons pas besoin de redéfinir le protocole. Et dans tous les cas, il ne sera pas nécessaire de modifier le code mais uniquement le protocole hoa://.

Communiquer avec un worker

Un worker représente un serveur, nous allons donc présenter son client qui permet de lui envoyer des tâches. Le client est très simple à utiliser, il suffit d'instancier la classe Hoa\Worker\Shared en précisant l'identifiant du worker, et ensuite utiliser la méthode adéquate pour envoyer des messages, à savoir Hoa\Worker\Shared::postMessage :

$worker = new Hoa\Worker\Shared('demorker');
$worker->postMessage('mail gordon@freeman.hl Hello Gordon!');

Bien sûr, le client va chercher le profil du worker dans le fichier hoa://Data/Variable/Run/workerId.wid. Si nous l'avons redéfini dans le worker, il faudra aussi le redéfinir dans son client.

Nous pouvons utiliser la méthode Hoa\Worker\Shared::postMessage autant de fois que nous le désirons mais attention, elle se connecte et se déconnecte à chaque fois du worker pour ne pas perturber l'exécution de notre application principale. Il faut alors penser à envoyer le maximum d'informations à chaque fois (par exemple à travers un tableau, les données seront sérialisées dans tous les cas).

Utiliser les commandes dédiées

Pour exécuter un worker, il faut avant tout démarrer PHP FPM :

$ php-fpm -d listen=127.0.0.1:9000

Ensuite, pour démarrer notre worker, nous allons utiliser Hoa en ligne de commande, et plus particulièrement la commande worker:start. Elle n'est qu'un alias pratique vers Hoa\Worker\Backend\Shared::start qui nécessite l'adresse de PHP FPM (par défaut 127.0.0.1:9000) et le chemin vers le fichier qui contient notre worker :

$ hoa worker:start /path/to/your/worker.php

Pour vérifier que notre worker a été créé, nous pouvons utiliser la commande worker:status qui va nous retourner la liste de tous les workers ainsi que des informations et statistiques associées comme les identifiants, adresses des serveurs, âge, consommation mémoire actuelle, moyenne et maximum etc. En réalité, elle n'est qu'un alias vers la méthode Hoa\Worker\Shared::getInformation. Ainsi :

$ hoa worker:status --run /path/to/wid/directory/
Shared worker informations

ID        PID   Socket                  Uptime      Messages  Last
demorker  2465  tcp://127.0.0.1:123456  0d00:03:15  0         -

demorker  ||||||||||||||||||||||||||||||||||||   |  1,398Kb 1,398Kb 1,536Kb

1 shared worker is running.

Note : le code couleur n'apparaît pas dans l'exemple.

Notre worker est maintenant en place. Nous pouvons exécuter le client sans problème (en ligne de commande, via un navigateur, peu importe) !

Enfin, pour arrêter le worker proprement, nous avons la commande worker:stop, qui n'est qu'un alias de Hoa\Worker\Backend\Shared::stop, nécessitant l'identifiant du worker et son mot de passe :

$ hoa worker:stop --run /path/to/wid/directory/ demorker
Password: ▋

Si le mot de passe est correct, le worker sera arrêté et le client ne pourra plus communiquer avec lui et lèvera une exception Hoa\Worker\Exception.

Conclusion

Hoa\Worker est une démonstration de ce qu'il est possible de faire avec Hoa\Zombie mais pas seulement. Il remplit parfaitement son rôle à savoir décharger l'application de traitements lourds et bloquants. Les commandes worker:* permettent d'administrer ces workers à moindre efforts. Rien ne vous empêche de bâtir votre propre solution à partir des concepts évoqués ici !

Une erreur ou une suggestion sur la documentation ? Les contributions sont ouvertes !

Comments

menu