J'essaie actuellement d'implémenter une file d'attente de travaux en php. La file d'attente sera ensuite traitée comme un travail par lots et devrait pouvoir traiter certains travaux en parallèle.
J'ai déjà fait quelques recherches et trouvé plusieurs façons de le mettre en œuvre, mais je ne connais pas vraiment leurs avantages et leurs inconvénients.
Par exemple. faire le traitement parallèle en appelant plusieurs fois un script via fsockopen
comme expliqué ici:
Traitement parallèle facile en PHP
J'ai trouvé une autre façon d'utiliser le curl_multi
les fonctions.
curl_multi_exec PHP docs
Mais je pense que ces 2 façons ajouteront à peu près des frais généraux pour créer un traitement par lots sur une file d'attente qui devrait principalement fonctionner en arrière-plan?
J'ai aussi lu sur pcntl_fork
qui semble également être un moyen de résoudre le problème. Mais cela ressemble à ça peut devenir vraiment désordonné si vous ne savez pas vraiment ce que vous faites (comme moi en ce moment;)).
J'ai également jeté un coup d'œil à Gearman
, mais là, je devrais également générer les threads de travail de manière dynamique selon les besoins et pas simplement en exécuter quelques-uns et laisser le serveur de tâches Gearman l'envoyer ensuite aux travailleurs libres. Surtout parce que les threads doivent être sortis proprement après l'exécution d'un travail, pour ne pas rencontrer d'éventuelles fuites de mémoire (le code peut ne pas être parfait dans ce problème).
Mise en route de Gearman
Donc ma question est, comment gérez-vous le traitement parallèle en PHP? Et pourquoi choisissez-vous votre méthode, quels avantages/inconvénients les différentes méthodes peuvent-elles avoir?
Merci pour toute contribution.
j'utilise exec()
. C'est facile et propre. Vous devez essentiellement créer un gestionnaire de threads et des scripts de threads, qui feront ce dont vous avez besoin.
Je n'aime pas fsockopen()
car cela ouvrira une connexion au serveur, qui se développera et pourrait atteindre la limite de connexion d'Apache
Je n'aime pas les fonctions curl
pour la même raison
Je n'aime pas pnctl
car il a besoin de l'extension pnctl disponible, et vous devez garder une trace des relations parents/enfants.
jamais joué avec gearman ...
Eh bien, je suppose que nous avons 3 options:
A. Multi-thread:
PHP ne prend pas en charge le multithread en natif. Mais il y a une PHP (expérimentale) appelée pthreads ( https://github.com/krakjoe/pthreads ) qui vous permet de faire exactement cela.
B. Multi-processus:
Cela peut se faire de 3 manières:
C. Traitement parallèle distribué:
Comment ça marche:
Client
envoie des données (message AKA) "peut être formaté JSON" au moteur (moteur MQ) "peut être local ou externe un service Web"MQ Engine
stocke les données "principalement dans la mémoire et éventuellement dans la base de données" dans une file d'attente (vous pouvez définir le nom de la file d'attente)Client
demande au moteur MQ de traiter les données (message) dans l'ordre (FIFO ou en fonction de la priorité) "vous pouvez également demander des données à une file d'attente spécifique".Certains moteurs MQ:
Plus d'entre eux peuvent être trouvés ici: http://queues.io
Si votre application doit fonctionner sous un environnement unix/linux, je vous suggère de choisir l'option forking. C'est essentiellement le jeu des enfants pour le faire fonctionner. Je l'ai utilisé pour un gestionnaire Cron et j'avais du code pour qu'il revienne à un chemin de code convivial Windows si la fourche n'était pas une option.
Les options consistant à exécuter plusieurs fois l'intégralité du script ajoutent, comme vous le dites, un peu de surcharge. Si votre script est petit, ce n'est peut-être pas un problème. Mais vous vous habituerez probablement à faire du traitement parallèle en PHP par la façon dont vous choisissez d'aller. Et la prochaine fois que vous avez un travail qui utilise 200 Mo de données, cela pourrait très bien être un problème. Donc, vous feriez mieux d'apprendre une manière avec laquelle vous pouvez vous en tenir.
J'ai aussi testé Gearman et je l'aime beaucoup. Il y a quelques choses à penser, mais dans l'ensemble, il offre un très bon moyen de distribuer des œuvres sur différents serveurs exécutant différentes applications écrites dans différentes langues. En plus de le configurer, de l'utiliser en réalité à partir de PHP, ou de tout autre langage d'ailleurs, c'est ... encore une fois ... le jeu des enfants.
Cela pourrait très bien être exagéré pour ce que vous devez faire. Mais cela vous ouvrira les yeux sur de nouvelles possibilités en ce qui concerne la gestion des données et des travaux, donc je vous recommande d'essayer Gearman pour ce seul fait.
J'utilise pnctl de PHP - c'est bon tant que vous savez ce que vous faites. Je comprends votre situation mais je ne pense pas que ce soit quelque chose de difficile à comprendre notre code, nous devons juste être un peu plus conscients que jamais lors de l'implémentation de la file d'attente JOB ou du processus parallèle.
Je pense que tant que vous le codez parfaitement et assurez-vous que le flux est parfait, vous devez garder à l'esprit le PROCESSUS PARALLÈLE lorsque vous l'implémentez.
Où vous pourriez faire des erreurs:
Jetez un coup d'œil à cet exemple - https://github.com/rakesh-sankar/Tools/blob/master/PHP/fork-parallel-process.php .
J'espère que cela aide.
Je préfère exec () et gearman. exec () est facile et sans connexion et consomme moins de mémoire. Gearman devrait avoir besoin d'une connexion de prise et le travailleur devrait prendre de la mémoire. Mais gearman est plus flexible et plus rapide que exec (). Et le plus important est qu'il peut déployer le travailleur sur un autre serveur. Si le travail demande du temps et des ressources. J'utilise gearman dans mon projet actuel.
Voici un résumé de quelques options de traitement parallèle en PHP.
Checkout Amp - Accès simultané asynchrone simplifié - cela semble être le plus mature PHP bibliothèque que j'ai vue pour le traitement parallèle.
Cette classe a été publiée dans les commentaires de la fonction exec () de PHP et fournit un véritable point de départ simple pour forger de nouveaux processus et en garder la trace.
Exemple:
// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');
// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);
// Then you can start/stop/check status of the job.
$process.stop();
$process.start();
if ($process.status()) {
echo "The process is currently running";
} else {
echo "The process is not running.";
}
Il y a aussi un excellent article Traitement asynchrone ou multitâche en PHP qui explique les avantages et les inconvénients de différentes approches:
Ensuite, il y a aussi ce tutoriel simple qui a été enveloppé dans une petite bibliothèque appelée Portier .
J'espère que ces liens fournissent un point de départ utile pour plus de recherches.
La méthode décrite dans 'Traitement parallèle facile en PHP' est carrément effrayante - le principe est OK - mais l'implémentation ??? Comme vous l'avez déjà souligné, les curl_multi_ fns offrent une bien meilleure façon de mettre en œuvre cette approche.
Mais je pense que ces 2 façons ajouteront à peu près les frais généraux
Oui, vous n'avez probablement pas besoin d'une pile HTTP client et serveur pour transférer le travail - mais à moins que vous ne travailliez pour Google, votre temps de développement est beaucoup plus cher que vos coûts matériels - et il existe de nombreux outils pour gérer HTTP/analyser les performances - et il existe une norme définie couvrant des éléments tels que les notifications d'état et l'authentification.
Une grande partie de la façon dont vous implémentez la solution dépend du niveau d'intégrité transactionnelle dont vous avez besoin et si vous avez besoin d'un traitement dans l'ordre.
Parmi les approches que vous mentionnez, je vous recommande de vous concentrer sur la méthode de requête HTTP en utilisant curl_multi_. Mais si vous avez besoin d'un bon contrôle transactionnel/pour la livraison des commandes, vous devez certainement exécuter un démon de courtier entre la source des messages et les agents de traitement (il existe un serveur à thread unique bien écrit pouvant être utilisé comme cadre pour le courtier ici ). Notez que les agents de traitement doivent traiter un seul message à la fois.
Si vous avez besoin d'une solution hautement évolutive, jetez un œil à un système de mise en file d'attente de messages approprié tel que RabbitMQ .
HTH
C.