Vortrag auf der Symfony UG Frankfurt zum Thema "Asychrone Event Verarbeitung" mit Symfony2 und RabbitMQ im Speziellen. Wir zeigen hier die Vor- und Nachteil, sowie einige Best Practices und Erfahrungswerte.
5. Warum benötigen wir asynchrone Verarbeitung?
● Langläufige Prozesse auslagern
● Reaktionszeit verkürzen
● Verlagerung von Last
● Microservices
● Parallelisierung von Prozessen
● Skalierbarkeit
● Austausch von Nachrichten mit anderen (Sub-)Systemen
7. Gearman
● Gearman Job Server (in C geschrieben)
● Läuft als Linux Daemon
● PECL Extension für Worker API
● Worker APIs für weiteren Sprachen (C, Perl,...)
9. Gearman
● PECL-Extension Version 1.1.2 von August 2013
● Letztes Server-Release von Anfang 2014
● Gefühlter Stillstand
● Gearmand und Extension oftmals inkompatibel / instabil
10. (PHP) Resque
● Portierung von Resque:
○ Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple
queues, and processing them later.
● Nutzt Redis(-Cluster)
● Redis beherrscht atomare Transaktionen (FIFO)
12. (PHP) Resque
● Seit 2012 unregelmäßig Commits im Master, letzter 2015-05-12
● chrisboulton/php-resque & michelsalib/BCCResqueBundle tot ?
13. RabbitMQ
Oder warum wir den Vortrag
“Asynchrone Event Verarbeitung mit RabbitMQ”
hätten nennen sollen
14. RabbitMQ
● Message Broker in Erlang geschrieben
● AMQP (Advanced Message Queuing Protocol)
● Offenes, aber binäres Netzwerkprotokoll
● Routing, Verteilen von Messages, etc.
● Transaktionen
● Weitere tolle Features
○ TTL
○ DLX (Dead Letter eXchange)
○ PreFetching
15. Vom publishen und consumen...
Publisher Publish Consumer
Ex-
change
QueueRoutes Consumes
16. There is a Bundle for it
● https://github.com/php-amqplib/RabbitMqBundle
● Consumer und Producer werden zu Symfony-Services
● Queue Consumer werden als Symfony Command ausgeführt
● Konfiguration via app/config.yml
○ Besser: app/config/rabbitmq.yml und in app/config/config.yml importieren
20. Erfahrungen mit Consumern
● PHP-Prozesse sind nicht für langläufige Prozesse gemacht
○ Ungewohnte Probleme: Memory Leaks, ...
● Mit Supervisor Consumer überwachen und neu starten lassen
● Offene Datenbank-Verbindungen, ggf. Timeouts = Beendigung bei Inaktivät
● Begrenzte Laufzeit pro Prozess (nach x Messages automatisch beenden)
● Memory Limit: RabbitMQ-Bundle hat eine Art “Soft-Quota”
● Anlaufen von Consumern dauert vergleichsweise lange
● Prefetching (Achtung: Reihenfolge!)
21. Message
● Kompakte Messages, Queues fressen Storage / RAM
● Allgemeines Format, z.B. JSON oder XML
○ Keine serialisierten PHP Objekte oder Array, um langfristig Interoperabilität mit anderen
System oder Sprachen zu gewährleisten
22. Message Transformation
● JMS/Serializer um Objekte nach JSON zu konvertieren
○ Im Consumer JSON-formatierte Strings zurück in Objekte
○ Objekte lassen sich dank Symfony Form und Asserts validieren
○ Alternativ: PHPs JsonSerializable Interface
○ Entities / Dokumente ggf. neu laden / aktualisieren (Unit of Work)
23. Message Header
● Message “Header” für Content-Type und Version
○ Messages könnten sich ändern, Consumer müssen kompatibel bleiben
● Eindeutige IDs machen das Logging / Debugging / Leben einfacher
● Weitere Metadaten:
○ Zeitstempel
○ User
○ App ID, etc.
25. Transaktionen
● Messages werden immer exakt einem Consumer zugewiesen
● Consumer muss explizit eine Nachricht mit “acknowledge” beantworten
● Andernfalls wird Nachricht rejected (and ggf. requeued)
○ Verwerfen heißt ggf. Datenverlust
○ Requeuing - Achtung:
■ könnte u.U. zu sog. Toxic Messages führen
■ könnte die Reihenfolge der Messages verändern
26. Toxic Messages
● Wird eine Message nicht explizit beantwortet, landet sie wieder in der Queue
● Wiederholt sich der Vorgang, haben wir eine Endlosschleife
27. Dead Letter Exchange
● RabbitMQ kennt daher die sog. Dead Letter Exchange (DLX)
● Queue bestimmt eine DLX, eine weitere Queue, in der alle Messages landen,
die zurückgewiesen wurden (Reject, TTL, Prefetch)
30. Deployment
● Consumer benötigen i.d.R. die aktuelle Code-Base
● Consumer benötigen einen “graceful” Shutdown
● Consumer sollten nur bei Inaktivät beendet werden
○ Sonst Message/Daten - Verlust
31. Und andere Herausforderungen
● Maßgebliche Änderung der Infrastruktur
○ Vorsicht bei der Partnerwahl / Abhängigkeit
● Last verschoben ist nicht aufgehoben
● Umdenken erforderlich
○ Statusanzeige
○ Zwischenstände
○ Push statt Pull / Websockets
● Abhängigkeiten von Messages
○ Insbesondere bei Parallelisierung !
● Performance (insg. mit Doctrine ORM / ODM)
32. Fragen ?
Danke :)
Diesen und andere Talks findet ihr auf:
https://www.gardenofconcepts.com/talks/
Talk bewerten nicht vergessen!