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
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 :
Hoa\Worker\Backend\Shared
qui permet de créer un worker partagé entre plusieurs processus ;Hoa\Worker\Shared
qui permet d'envoyer des messages vers le worker.
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 !