Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Monolithic to Multi-tier

From Monolithic to Multi-tier

Architektur und Entwicklung einer Support-Platform mit Telefonie- und Videofunktion mit Fokus auf Entkopplung der einzelnen Komponenten (PHP/Symfony API, Node.js Realtime/Websocket Server, HTML5 Frontend und RabbitMQ als verbindender Message Bus)

Avatar for Pascal Cremer

Pascal Cremer

January 04, 2017
Tweet

More Decks by Pascal Cremer

Other Decks in Technology

Transcript

  1. Who's that guy..? ‣ Scientific Programming an der FH Aachen

    (2000) ‣ Mathematik, Informatik & Physik ‣ C/C++, FORTRAN, Java, R, MATLAB, FEMLAB etc. ‣ Abschluss als Diplom-Mathematiker, FH (2006) ‣ Web-Development (2006) ‣ PHP, MySQL, Javascript ‣ Mobile Development (2008) ‣ iOS
  2. We screwed up! (kind of...) ‣ Mischung aus prozeduralen und

    objektorientierten Code ‣ Fehlende Trennung zwischen Business-Logik und Präsentation ‣ Spärliche Umsetzung von Enterprise Design Patterns ‣ Enge Kopplung, fragiler Code ‣ Begrenzte (teils unmögliche) Testbarkeit ‣ "Missbrauch" von MySQL ‣ Livedaten..? Logging..? Data Processing..? ಠ_ಠ
  3. The next big thing! ‣ Chat-Plattform ‣ Agents & User

    ‣ Audio und/oder Video-Chats ‣ Call-In Funktion per Service-Rufnummer ‣ Sessions ‣ Real-time Events ‣ Flexibel und erweiterbar ‣ Horizontal skalierbar ‣ Whitelabel-fähig
  4. The next big thing! ‣ Chat-Plattform ‣ Agents & User

    ‣ Audio und/oder Video-Chats ‣ Call-In Funktion per Service-Rufnummer ‣ Sessions ‣ Real-time Events ‣ Flexibel und erweiterbar ‣ Horizontal skalierbar ‣ Whitelabel-fähig
  5. Real-time Events (Motivation) ‣ User Experience & Qualitätssicherung ‣ Mögliche

    Events ‣ Agent ändert seinen Status ‣ Session wird gestartet, verlängert oder beendet ‣ Fehler- / Ausnahnmefälle ‣ Event-Propagierung an mehrere Komponenten ‣ Frontend, Stats, Chat-Server, Tech-Support etc.
  6. Real-time Events (Realisierung I) ‣ Zentrale Service-App ‣ PHP 5.4

    & Symfony 2.1 ‣ RESTful API zur "Annahme" von Events ‣ MySQL DB für "historische" Daten ‣ Redis Key-Value Store für Livedaten und Statistiken ‣ RabbitMQ zur Event-Propagierung
  7. Real-time Events (Realisierung II) ‣ Node.js Server ‣ Kommunikation mit

    dem Frontend ‣ Websockets (Socket.io) ‣ Permanente Verbindung zum RabbitMQ ‣ Frontend ‣ Backbone.js App ‣ Kommuniziert ausschließlich mit Node.js Server ‣ d.h. keine sonstigen Abhängigkeiten
  8. Symfony 2.1 ‣ PHP 5.3 Application-Framework ‣ OpenSource (MIT License)

    ‣ Entwickelt von Sensio Labs (2005) ‣ MVC, Dependency Injection, Observer etc. ‣ "Makes PHP suck less" ‣ Fantastische Community ‣ Doctrine, Monolog, Composer, Behat etc.
  9. Node.js ‣ PHP schlecht geeignet für lang laufende Prozesse ‣

    Node.js als Alternative ‣ OpenSource (MIT License) ‣ Entwickelt von Ryan Dahl / Joyent (2009) ‣ Basierend auf Googles V8 Javascript Engine ‣ Event-driven, non-blocking I/O ‣ Scalable by design ‣ Socket.io für WebSockets
  10. RabbitMQ ‣ Open Source Message Broker ‣ Entwickelt von SpringSource

    / VMWare ‣ Implementiert das AMQP-Protokoll ‣ Cluster & Failover Support ‣ "Fire & Forget" ‣ Verschiedene Routing-Topologien ‣ Fanout, Direct, (simple) Routing, Topic ‣ 1st & 3rd Party Client Support
  11. Produce r Consumer 2 Exchange Queue: *blue.* Queue: red.* Consumer

    1 Queue: *.yellow Consumer 3 topic: blue.yellow
  12. RabbitMQ (Cont.) ‣ Messages ‣ Headers & Body/Payload frei wählbar

    ‣ Header (z.B.): content-type => application/json ‣ Payload (z.B.): JSON-encoded ‣ Message Acknowledgement / Rejection ‣ Prefetching ‣ TTL per Queue / Message ‣ Queue Purging
  13. Redis ‣ Key-Value Store (mit netten Extras) ‣ "Schweizer Taschenmesser"

    ‣ Open Source (BSD License) ‣ Entwickelt von Salvatore Sanfilippo (2009) ‣ Ordentlich schnell und performant ‣ bis zu 100.000 w/s und 80.000 r/s ‣ Native Datenstrukturen ‣ Lists, Hashes, Sets, Sorted Sets, Pub/Sub
  14. pool:agents:online Agent 1 Agent 2 Agent 4 Agent 3 Agent

    5 pool:agents:busy Agent 3 Agent 5 SADD "agent5" "pool:agents:busy"
  15. pool:agents:online Agent 1 Agent 2 Agent 4 Agent 3 Agent

    5 pool:agents:busy Agent 3 Agent 5 Agent 1 SDIFF "pool:agents:online"
  16. pool:agents:online Agent 1 Agent 2 Agent 4 Agent 3 Agent

    5 pool:agents:busy Agent 3 Agent 5 Agent 1 { Online-Agents, die nicht beschäftigt sind } Agent 2 Agent 4
  17. Redis (Cont.) ‣ Commands / Operationen ‣ Transaction Support ‣

    Key TTL ‣ Disk Persistence ‣ Scriptable (Lua) ‣ Weitere Use-Cases ‣ Caching ‣ Statistiken
  18. Real-time Events (Beispel: Agent-Anmeldung) ‣ API-Call des Chat-Servers an Service-App

    ‣ Service-App legt einen Eintrag für den Agent im Online-Pool (Redis) an ‣ Service-App published eine Nachricht ans RabbitMQ ‣ RabbitMQ verteilt die Nachricht per Fanout an alle verbundenen Queues ‣ Node.js Server konsumiert die Nachricht aus dem RabbitMQ ‣ Node.js Server schickt die Information per WebSockets ans Frontend ‣ Frontend updatet seine HTML-Darstellung
  19. Flexibel & erweiterbar (Motivation) ‣ Hinzufügen neuer Funktionalitäten ‣ Möglichst

    wenig Logik im zentralen Service ‣ "App-Silos" ‣ Belohnung ‣ Schnellere Iteration ‣ Vermeidung/Verringerung von Regressionen ‣ Einfachere Wart- und Testbarkeit
  20. Flexibel & erweiterbar (Realisierung) ‣ RabbitMQ als zentrales Instrument ‣

    Einfaches Erweitern durch neue Queues & Consumer ‣ Fanout Exchange für "Broadcasting" ‣ Verteilte Verarbeitung ‣ Möglichkeit verschiedene Programmiersprachen zu verwenden ‣ Entkopplung der Komponenten (Apps) ‣ Klar definierte "Schnittstellen" ‣ Beispiel: Qualitätssicherung
  21. “ Kann die Leitung eines Agents mehrere Male hintereinander nicht

    erreicht werden, muss der Agent aus der Online-Liste entfernt werden und der Tech-Support benachrichtigt werden.
  22. “ Die aktuelle Performance der Agents soll Einfluss auf die

    Sortierung im Frontend haben. Agents mit besonders langen Sessions sollen weiter vorne dargestellt werden.
  23. Data-Aggretation ‣ Stats-Consumer ‣ Aggregation mittels Redis Datenstrukturen ‣ z.B.

    Sorted Sets für Session-Duration per Agent ‣ Live-Statistiken ohne "hohe Kosten" ‣ Real-time Gewichtung für Sortierung im Frontend ‣ Regelmäßige Archivierung in MySQL-Table ‣ z.B. stündlich, täglich, wöchentlich, monatlich etc.
  24. Data-Aggregation (Cont.) ‣ Session-Duration per Agent ‣ Sorted Sets ‣

    Keine doppelten Elemente ‣ Built-in Scoring ‣ Commands für Rankings ‣ Update nach jeder erfolgreichen Session ‣ Nur eine Metrik von vielen Agent 1 Agent 2 Agent 4 Agent 3 100 200 250 300 stats:agents:durations
  25. Horizontale Skalierung (Motivation) ‣ Leistungssteigerung durch Hinzufügen neuer Server-Instanzen ‣

    Werbemaßnahmen ‣ Eigenwerbung (z.B. TV) ‣ Affiliate-based Advertisement ‣ Lastskalierbarkeit ‣ Zeitkritisch / kurzfristig
  26. Horizontale Skalierung (Node.js) ‣ Simple Server-Implementierung ‣ (Dauerhafte) Verbindung zum

    RabbitMQ ‣ Broadcasting an alle verbundenen Clients ‣ Unidirektionale Kommunikation (derzeit) ‣ Benchmark: ~ 9000 - 10000 concurrent Connections pro Server ‣ Neue Server-Instanz <-> Neuer Worker für Queue(s) ‣ Lastverteilung ‣ HAProxy, ldirectord etc.
  27. Horizontale Skalierung (RabbitMQ) ‣ RabbitMQ Cluster ‣ Lastverteilung ‣ High-Traffic

    Queues auf verschiedenen Nodes ‣ Unterstützung durch eigene Topologien ‣ Round-robin Dispatching ‣ Message Prefetching, Acknowledgement ‣ Out-of-the-box Performance ‣ Multi-threaded, Multi-Core Support (Erlang) ‣ Kleiner Memory-Footprint
  28. Horizontale Skalierung (Redis) ‣ Partitioning / Sharding ‣ Redis-Cluster (unstable)

    ‣ Proxy (assisted) Sharding ‣ Twemproxy / Nutcracker ‣ Client-side Sharding ‣ Predis (PHP) ‣ Presharding ‣ Einfache Replikation
  29. Whitelabel (Motivation) ‣ Teil der Affiliate-Vermarktung ‣ Nutzung von Content

    und Technologien ‣ Re-Branding (Logos, Farben, Layout etc.) ‣ Zielgruppenerweiterung ‣ Provisionsmodell ‣ Hosted & Self-Hosted
  30. Whitelabel (Realisierung) ‣ Trennung von Frontend und Service-Komponenten ‣ Javascript,

    HTML & CSS ‣ Installation / Konfiguration = trivial ‣ Eat your own dog food ‣ n Frontends statt einem Frontend ‣ Generiert aus einer einzigen Codebase ‣ Maintenance win!
  31. Herausforderungen ‣ Planungsaufwand ‣ Komplexität ‣ Neue, teils junge, Technologien

    ‣ Polyglotte Datenpersistenz ‣ "Merging" von Daten aus verschiedenen "Stores" ‣ Datenkonsistenz trotz asychronen Worflows
  32. Herausforderungen (RabbitMQ) ‣ RabbitMQ & Hochverfügbarkeit ‣ Keine Replikation von

    Queues und Messages (default) ‣ "Mirrored Queues" ‣ "Iterative" Synchronisierung für neue Slaves ‣ Explizite Sychronisierung möglich, lockt aber die zu synchronisierende Queue
  33. Herausforderungen (Redis) ‣ Redis-Cluster nicht vor Version 3.0 ‣ Sharding

    / Partitioning Limitierungen ‣ Operationen mit mehr als einem Key problematisch ‣ Kein Support für Transactions mit mehreren Keys ‣ Client-seitiges Partitioning auf Kosten von Performance ‣ Hinzufügen von neuen Nodes nicht trivial ‣ ...bis unöglich bei Client-seitigem Partitioning ‣ Presharding als Workaround