messages queues - socloz@phpforum 2013
DESCRIPTION
1/ Retour d'expérience sur la mise en place d'une message queue pour SoCloz - http://www.socloz.fr. - première phase : job queue, résolu par la mise en place de beanstalk - deuxième phase : pub/sub. Alternatives évaluées : NSQ (en complément de beanstalk) et RabbitMQ. Adéquation fonctionnelle : léger avantage pour beanstalk (job), égalité (pub/sub) Simplicité : avantage pour beanstalk/NSQ Durabilité : avantage RabbitMQ 2/ Etat des lieux des solutions de message queueTRANSCRIPT
Job queues, messages queues état des lieux & retours d'expérience
PHP Forum 2013 Jean-François Bustarret (CTO), Sylvain Lassaut (Lead Dev)
SOCLOZ ? Un peu de contexte…
15/11/13 SoCloz - Tous droits réservés 2
Socloz : l’équipe
• Fondée en 2010 • En ligne depuis novembre 2011 • Deuxième levée de fond bouclée • 10 personnes (pas de stagiaires) • 5 embauches en cours
15/11/13 SoCloz - Tous droits réservés 3
SoCloz : le produit
15/11/13 SoCloz - Tous droits réservés 4
Moteur de recherche de produits en magasin 1 500 000 produits dans plus de 10 000 magasins et 150 enseignes
www.socloz.fr SFR Shopping [mobile] Le Guide Mappy Shopping … Un système de réservation Naf-Naf Le Tanneur Guy Degrenne …
SoCloz : l’architecture
15/11/13 SoCloz - Tous droits réservés 5
Architecture à base de micro-services Frontend : PHP Symfony2 • Backend : Go/PHP (Erlang) • 14 serveurs
frontend récep,on des flux
enseigne
importa,on
indexa,on
API internes
normalisa,on enrichissement
MESSAGES QUEUES : GÉNÉRALITÉS Principes de bases, patterns d’utilisation et critères de choix
15/11/13 SoCloz - Tous droits réservés 6
Serveur 2
Message queues : principe de base
15/11/13 SoCloz - Tous droits réservés 7
Une message queue, comment ça marche ? Serveur 1
consommateur
consommateur
consommateur
broker producteur
Message queues : patterns d’utilisation
15/11/13 SoCloz - Tous droits réservés 8
Point à point (job queue, RPC)
consommateur
consommateur
consommateur
broker producteur
Message queues : patterns d’utilisation
15/11/13 SoCloz - Tous droits réservés 9
Publish-subscribe / fan-out
consommateur
consommateur
consommateur
broker producteur
Message queues : patterns d’utilisation
15/11/13 SoCloz - Tous droits réservés 10
Publish-subscribe / fan-out
broker producteur
consommateur
consommateur
consommateur
Message queues : critères de choix
• Besoins fonctionnels • Point à point ou fan-out • Traitements différés • Rejeu/Rejeu différé en cas de plantage de worker • Priorités
• Garanties • Durabilité & Délivrabilité (plantage broker, consommateur inactif) • Garantie d’unicité • Garantie d’ordre
• Débit
Qu’est ce que je suis capable d’exploiter ? Un outil universel et complexe ou deux outils spécialisés et simples ?
15/11/13 SoCloz - Tous droits réservés 11
PROBLÉMATIQUE #1 Traitement des flux
15/11/13 SoCloz - Tous droits réservés 12
Problématique #1 : traitement des flux
Besoin
Solution : beanstalkd
15/11/13 SoCloz - Tous droits réservés 13
• Job queue (priorité, délai) • Catégorisation (tubes) • Protocole simple et robuste : clients disponibles pour la
plupart des langages
Parallélisation de traitements
Beanstalk : exemple de code
Producteur // initialisation $pheanstalk = new Pheanstalk_Pheanstalk( '127.0.0.1' ); $pheanstalk->useTube('test'); // envoi d'un message $pheanstalk->put("hello world");
Consommateur // initialisation $pheanstalk = new Pheanstalk_Pheanstalk( '127.0.0.1' ); $pheanstalk->watch('test'); // boucle de traitement des messages while (true) { $job = $pheanstalk->reserve(); try { // traitement ... echo $job->getData(); // suppression $pheanstalk->delete($job); } catch (Exception $e) { // requeue (priorité par défaut, délai 0) $pheanstalk->release($job, null, 0); } }
15/11/13 SoCloz - Tous droits réservés 14
pda/pheanstalk
Beanstalk : analyse
Avantages
• performant : in-memory, event-driven • facile à mettre en place (pas de conf)
Inconvénients
15/11/13 SoCloz - Tous droits réservés 15
• pas de réplication / cluster • support durabilité minimal / expérimental • Linux & FreeBSD uniquement
PROBLÉMATIQUES #2 ET #3 Statistiques Agents
15/11/13 SoCloz - Tous droits réservés 16
Problématique #3 : statistiques
Besoin Décompte des vues produits/marques/magasins/catégories de 1 à >100 compteurs sur une page
Solution initiale Ecritures en base depuis le front Maximum 3 écritures
15/11/13 SoCloz - Tous droits réservés 17
Tops produits/marques/magasins/catégories
Map/Reduce
• Trop d’écritures en base • Coût des map-reduce • « Tu me ferais le top marques de chaque catégorie ? En temps réel ? »
Problèmes
Fort volume, haute dispo, faible criticité
Nouveau besoin
Problématique #4 : agents
Besoin Traitements asynchrones sur les données importées • enrichissement de données (http, …) • normalisation • géocodage des adresses des magasins • téléchargement d’images • …
Solution initiale Planification (polling) Stockage d’un état en base de données 3 requêtes à chaque planification : • Nouvelles données • Réessais • Mises à jour
Envoi de tâches dans Beanstalkd
15/11/13 SoCloz - Tous droits réservés 18
• Requêtes de planifications coûteuses • Ce serait mieux avec de vrais observers
Problèmes
Pub/sub, faible criticité
Nouveau besoin : observers
Solution #1: NSQ
15/11/13 SoCloz - Tous droits réservés 19
NSQ, Matt Reiferson @ bitly (2012) https://github.com/bitly/nsq https://github.com/davegardnerisme/nsqphp
topic producteur
consommateur
consommateur
consommateur
channel
NSQ : architecture
15/11/13 SoCloz - Tous droits réservés 20
producteur
consommateur
nsqd
nsq lookupd
nsq lookupd
nsqd nsqd nsqd
Quels nsqd produisent ce topic ?
Envoi de messages sur un/plusieurs nsqd
Connexion à tous les nsqd
simultanément
Notification des nsqlookups de la présence du topic
NSQ : exemple de code
Producteur // initialisation $nsq = new nsqphp\nsqphp(); $nsq->publishTo('localhost'); // envoi d'un message $nsq->publish( 'test', new nsqphp\Message\Message('hello world') );
Consommateur // initialisation $nsq = new nsqphp\nsqphp( new nsqphp\Lookup\FixedHosts('localhost:4160') ); $nsq ->subscribe('test', 'channel1', function ($msg) { // traitement... echo $msg->getPayLoad(); }) ->subscribe('test', 'channel2', function ($msg) { // traitement... echo $msg->getPayLoad(); }); // boucle de traitement $nsq->run();
15/11/13 SoCloz - Tous droits réservés 21
nsqphp
NSQ : contraintes sur le client
Problème
Solution
15/11/13 SoCloz - Tous droits réservés 22
E/S asynchrones (React) http://reactphp.org/
• écouteurs (callback) d’événements (écriture, lecture...) sur descripteur (fichier, connexion)
• timers (appel différé) • plusieurs backends disponibles : libev, libevent, select
écouter plusieurs connexions nsqd en parallèle
NSQ : conclusion
Avantages facile à mettre en place • pas de conf • topic / channel créés à la volée
haute disponibilité • support simple et robuste
admin web
Inconvénients contraintes sur le client
idempotence
15/11/13 SoCloz - Tous droits réservés 23
• Idéal pour pub/sub • Peu adapté à notre besoin de job queue
Conclusion
Solution #2 : RabbitMQ/AMQP
AMQP (Advanced Message Queuing Protocol) • architecture programmable : exchange / queue (point à point, fan-out, …) • durabilite (réglable par message) • authentification / contrôle d'accès RabbitMQ • Ecrit en Erlang @ Rabbit Technologies (2008) • Protocoles AMQP, HTTP(S), XMPP... • Gestion de plugins (Erlang) • Cluster / réplication
Client PHP : php-amqplib, amqp (pecl)
15/11/13 SoCloz - Tous droits réservés 24
RabbitMQ : exemple de code (pub/sub)
Producteur // initialisation $connection = new AMQPConnection( 'localhost', 5672, 'guest', 'guest' ); $channel = $connection->channel(); $channel->exchange_declare( 'test', 'fanout' ); // envoi d'un message $channel->basic_publish( new AMQPMessage("hello world"), '', 'test' );
Consommateur // initialisation $connection = new AMQPConnection( 'localhost', 5672, 'guest', 'guest' ); $channel = $connection->channel(); $channel->exchange_declare( 'test', // nom 'fanout' // type ); list($queue_name, ,) = $channel->queue_declare(); $channel->queue_bind($queue_name, 'test'); $channel->basic_consume( $queue_name, '', false, true, false, false, function ($msg) { // traitement echo $msg->body; } ); // boucle de traitement while(count($channel->callbacks)) { $channel->wait(); }
15/11/13 SoCloz - Tous droits réservés 25
php-amqplib
RabbitMQ ou beanstalkd + NSQ ?
Job queue : beanstalkd vs RabbitMQ
Pub / sub : NSQ vs RabbitMQ
15/11/13 SoCloz - Tous droits réservés 26
1. Réponse au besoin fonctionnel : NSQ ≈ RabbitMQ 2. Simplicité : NSQ >> RabbitMQ 3. Délivrabilité/Durabilité : RabbitMQ > NSQ
1. Réponse au besoin fonctionnel : beanstalkd > RabbitMQ 2. Simplicité : beanstalkd >> RabbitMQ 3. Disponibilité : RabbitMQ >> beanstalkd
Simplicité totale : NSQ + beanstalkd > RabbitMQ
AUTRES OUTILS Voire autres problématiques…
15/11/13 SoCloz - Tous droits réservés 27
Autres outils : les plus simples
Redis (C) Pub/sub simple, job queues simples. En direct ou avec un surcouche (ex: resque – GitHub pour Ruby) Les - : fonctionnel limité (pas de rejeu, pas de différé) http://redis.io/
Gearman (C – LiveJournal, digg) RPC et job-queues Les - : pas optimal en job-queue, pas de clusterisation http://gearman.org/ http://pecl.php.net/package/gearman
Kestrel (Scala - twitter, foursquare, tumblr) Job queue & pub/sub, protocole memcache Les - : assez lourd, nécessite un minimum de connaissance de Scala https://github.com/robey/kestrel http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/
Darner (C++ - wavii) Dérivé de kestrel, plus simple, meilleurs performances Les - : wavii racheté par Google, pérennité ? https://github.com/wavii/darner
IronMQ (SaaS) Fonctionnellement très complet et simple à mettre en place Les – : pas gratuit http://www.iron.io/mq
15/11/13 SoCloz - Tous droits réservés 28
Autres outils : les plus complexes
Amazon SNS/SQS (SaaS) SNS (pub/sub) et SQS (job queue), à coupler éventuellement Les – : pas gratuit, latences http://aws.amazon.com/fr/sns/ et http://aws.amazon.com/fr/sqs/
Marconi (C – Openstack) Réponse d’OpenStack à SNS/SQS. Basé sur 0MQ, utilise MongoDB/QPID pour le stockage Les – : jeune (mais prometteur) https://wiki.openstack.org/wiki/Marconi
Celery (Python – Instagram) Couche d’abstraction au dessus d’un broker (RabbitMQ, Redis, MongoDB, CouchDB, SQS, IronMQ, …) Les – : complexité (connaissance de Python recommandée) http://www.celeryproject.org/
0MQ Librairie C, avec extension PHP PECL http://zeromq.org/ http://pecl.php.net/package/zmq
AMQP QPID - http://qpid.apache.org/ ActiveMQ - http://activemq.apache.org/, Apollo - http://activemq.apache.org/apollo/ HornetQ - http://www.jboss.org/hornetq
15/11/13 SoCloz - Tous droits réservés 29
Autres problématiques : event/log processing
Distribué, performant, fonctionnel limité Conçus souvent pour transporter des logs vers des systèmes de type Hadoop, mais utilisables pour faire des traitements
Kafka (Java - LinkedIn, Tumblr, Twitter) http://kafka.apache.org/
Fluentd (C/Ruby – Line, SlideShare) http://fluentd.org/
Scribe (C++ - Facebook, Digg, Zynga) https://github.com/facebook/scribe
Flume (Java - Cloudera) https://cwiki.apache.org/confluence/display/FLUME/Home
15/11/13 SoCloz - Tous droits réservés 30
Autres problématiques : Stream processing
Storm - (Java/Clojure – Twitter, Groupon) Des spouts injectent des flux de données qui sont traités par un graphe de bolts, développés dans des langages variés (java, python, ruby, PHP, …) http://storm-project.net/ et https://github.com/Lazyshot/storm-php
15/11/13 SoCloz - Tous droits réservés 31
spout
bolt
spout spout
bolt
bolt bolt bolt
Merci ! SoCloz recrute : - Un dev frontend (HTML/CSS/PHP+Symfony2) - Un dev backend (PHP+Symfony2/Go) - Un devops (Linux/Go/PHP) [email protected]
http://www.socloz.fr @SoClozTech / @jfbus