Ulrich Lusseau - www.mon-code.net
11 ans d'XP pro
PHP depuis 2002
Sf depuis 2008
Éleveur de lapin depuis 5 ans
Baby devops
Refonte d'un projet de synchronisation de calendrier
App -> SOGo : temps "quasi réel" avec RabbitMQ
SOGo -> App : crontab
2 instances
1 vhost pour le projet
1 exchange type direct
6 queues
Projet Symfony 2 dédié
Lib php amqp
RabbitMQBundle
Aucune idée de la charge
Application utilisée aux heures de bureau
Cron ou Deamon
Cron :
- Programmé toutes les 5 minutes
- Consommation 1000 messages ou TTL 5 minutes
Autonomie vis à vis de l'infogérant
Facile à appréhender pour l'équipe
Plus simple à arrêter qu'un daemon
Format JSON
Plus petit possible
Headers dans le payload pour faciliter le debug
{
"headers": {
"date": "2018-05-18 14:00:00",
"exchange": "afup",
"routingkey": "phptour2018"
},
"body": {
"event_id": 42
}
}
Erreur mal gérée, fait planter le worker
+
Stratégie du worker : message NAK et remis en queue
=
boucle infinie
Catcher les erreurs dans le worker
Publier les messages dans une queue d'erreur
ACK les messages
Serveur de cron planté
Problème réseau
Impossible de publier dans RabbitMQ
Si RabbitMQ indispo alors envoie du message par mail
Un matin : 10 000 mails
RoutingKey ne correspond pas entre l'application et la déclaration dans RabbitMQ
Perte du message sans aucune alerte
Utilisation de l'option Alternate-exchange
Création d'un exchange type Fanout avec sa queue.
Utilisation d'une Policy pour appliquer un Alternate-Exchange sur tous les exchanges existants.
Le monitoring est important pour avoir une vision de l'utilisation et la tendance :
- nombre message/queue
- taille des queues
Besoin d'absorber ponctuellement des grosses charges
Wrap des workers avec un appel sur l'API du plugin management pour connaître le nombre de messages dans la queue et le nombre de workers en cours
Augmentation de la fréquence du cron des workers
Mettre en place de l'alerting
0 message publié en x heures
Nombre message > Y dans les queues
Volonté de mutualiser le code entre les projets
Les nouveaux projets
Gains :
Stack de processor (decorator) = plus modulaire
Lib + Bundle plus facile a intégrer dans du legacy
Pertes :
Pas de configuration de RabbitMQ (queue, exchange...)
Impossible de connaître le nombre de consumer (PR#169)
Ack message, exception catcher, max message, memory limit ...
Un traitement qui échoue a instant t peut réussir à un instant t+x
Mixe des options : TTL, DLX et DLK
Attention au retry infini :
- mettre le nombre de retry dans le payload
- utiliser X-DEATH dans les headers du message
Engorgement de la queue d'erreur
Beaucoup de faux positif
Nécessite beaucoup de temps à dépiler
MySQL has gone away :
NACK/requeue du message et fin du worker
API qui ne répond pas :
ACK du message et publication pour les mettre en queue de retry
Autres erreurs :
ACK du message et publication pour les mettre en queue d'erreur
Tous les messages arrivent dans la même queue d'erreur
Nécessite beaucoup de temps pour dépiler les messages
Une queue d'erreur dédiée par queue "applicative"
Plus facile pour le monitoring et l'alerting
1 vhost / projet
1 seul utilisateur
+90 queues
Les mêmes instances RabbitMQ pour tous = spof
1 vhost / domaine fonctionnel du projet
1 utilisateur / projet / vhost
1 instance|cluster RabbitMQ / projet
CLI nécessite les droits root ou config sudo
Plugin Management un peu laborieux pour la gestion des queues, exchanges, ...
CLI du plugin management nécessite un accès SSH et tout aussi laborieux que l'UI
Création d'un outil dédié, à destination des dévs
Call de l'API du plugin Management
Fichier de conf Yaml
Projet open source : https://github.com/metfan/rabbit-setup
rabbit_setup:
connections:
default:
user: guest
password: guest
host: 127.0.0.1
port: 15672
vhosts:
collector: #vhost name
connection: default
policies:
AE:
pattern: "collector"
apply-to: exchanges
definition: {alternate-exchange: unroutable}
exchanges:
unroutable:
type: fanout
collector:
type: direct
queues:
unroutable:
bindings:
- { exchange: unroutable, routing_key: null }
picture:
bindings:
- { exchange: collector, routing_key: picture}
Commande de validation de la config
Commande de création de la config
Projet de signature électronique
Session de signature valide 14 jours
1 queue classique pour checker le status
Pendant les 23 heures suivantes :
1 queue de retry avec un TTL de 30 minutes
Jusqu'à expiration de la session :
1 queue de retry avec un TTL de 1h
Pendant la première heure :
1 queue de retry avec un TTL de 5 minutes