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

Heavy Lifting

Mario Mueller
September 07, 2012

Heavy Lifting

Mario Mueller

September 07, 2012
Tweet

More Decks by Mario Mueller

Other Decks in Technology

Transcript

  1. trivago business facts • Hotel Meta-Suche mit ~130 Partnern und

    mehr als 550.000 Hotels • bis zu 1.000.000.000 PHP Req. / Monat • > 20 Sprachen • aktuell 30 Länder-Plattformen
  2. trivago Teilbereiche • Hotelsuche und Preisvergleich • Community mit Bewertungen

    und Bonusprogramm (UGC) • Hotelier Plattform (UGC) • Partner Plattform mit Statistiken und Informationen zur jeweiligen Partner- Anbindung (non-pulic)
  3. trivago Technik • PHP 5.3 / JavaScript / Java /

    C / Bash • FreeBSD • Apache / Percona / Memcache / Redis • Diverse CDN Provider • Direkte Level 3 / NTT Anbindung
  4. • PHP 5.2 kompatibler Code • ca. 1.2 Mio. Zeilen

    • Teilweise > 5 Jahre alt • Ein Mix aus prozedualem, teilw. objektorientiertem und "Ninja" - Code mit $GLOBALS, global und einer Menge "&". "Legacy"
  5. Zielsetzung • Hohe first-byte Performance (um oder unter 200ms, aktuell

    175-350ms) • Steigerung der Wartbarkeit und Erweiterbarkeit • Testbarkeit des Codes sicherstellen • Auftrennung des Codes nach OOP Mustern (SOC, IOC, ...)
  6. • Ist für trivago technisch der wichtigste KPI • Alle

    PHP Requests (weltweit) werden aus Düsseldorf bedient. • Kein CDN / HTTP Caching für HTML • Pro Suche zwischen 10 und 100 AJAX Requests (Polling, Filtering, etc.) Performance
  7. Zend Framework 2 • Performance- Overhead ~60ms • Wenig Dokumentation

    • Unklare API Stabilität, da Beta Kontrahenten Flow 3 • Performance- Overhead ~300ms • Akzeptable Dokumentation
  8. Symfony 2 • Performance Overhead ~60ms • Akzeptable Dokumentation •

    2.0 mit mehreren Patch-Releases • Bonus: Bisherige Architektur Planung passt gut in das Symfony Konzept
  9. Allerdings ... • Kein Doctrine ◦ Zu langsam für unsere

    Bedürfnisse ◦ Bei stark denormalisierten Daten macht ein ORM keinen Spaß mehr • Kein Monolog im "prod" Env. • XML statt YAML (XSDs, weniger anfällig)
  10. Konzept Idee • Separation of Concerns !important; • Web Framework

    von Business Code trennen (Physikalisch & Architektur) • trivago's Business Code enthält keine Referenzen auf Symfony APIs • Ausnahme: Symfony APIs mit eigener Impl. (Security, Event Listener, Twig Extensions).
  11. • Components ◦ Keine Queries (Kosten / Nutzen) ◦ Keine

    Entities (Dürfen keine Dependencies haben) • Services • Business Cases • Traits als alternativer Ansatz Service Container
  12. Grundlegender Aufbau Components (DB Pooling, Locale/Lang Handling, etc) Query (pro

    Query eine Class) Entities ("dumme" Klassen mit public Properties) Services (Datenbeschaffung durch Components, Cache Steuerung, Aggregation mehrerer Services) Business Cases (Modellierung der Geschäftslogik durch die Verwendung von Services) Symfony2 Controller In manchen Fällen erw- eist sich ein Business Case als ineffizient
  13. Vorab • Die XML Beispiele in der Online-Doku sind häufig

    unvollständig, die XSDs sind die bessere Doku. • Konfiguration pro Hostname + config_local für lokale Überlagerung macht Sinn • Versioniertes Cache-Dir (Release ID) um zwei Stände gegen einander zu halten + Rollback wenns brennt
  14. Alpha Version • Konnte noch nicht viel, gemessen am Projektziel

    • Brauchte 900 - 1500ms bis first-byte • Ajax Calls lagen bei ~600ms • Company-interner Test mit ~80 Usern.
  15. Symfony 2 • Listener zusammengefassen, weniger ist mehr • Serverseitiges

    Rendern von HTML für AJAX veringert, durch json_encode ersetzen • Erster Versuch: Universal Classloader ggn XCacheClassloader ersetzen. #fail • Statischer Autoloader (@arneblankerts) #win
  16. Beta Version • Konnte schon ein Bisschen mehr • First-byte

    bei 600 - 700ms • Ajax Calls bei 400 - 460ms • Erster Live-Test in Frankreich
  17. • Mehrere AppKernels + eigenen AbstractAppKernel bringen Ordnung (und Performance)

    • Konfigurationen mit mehr als 4 Environments sucken • addClassesToCompile() nutzen! Symfony 2
  18. Twig • Autoescape abschalten. Händisch escapen +15% Performance • ext/Twig

    nutzen! Twig's getAttribute ist teuer! • Macros vermeiden, besonders in Loops!
  19. Release Candidate • Funktionalität produktionsreif • First-byte bei ~300ms •

    Ajax Calls bei < 200ms • Mehrere Live-Tests in Frankreich und Deutschland
  20. Assetic • Base URLs shuffeln ist machbar, reicht uns aber

    nicht • Base URL - Bestimmung zur Laufzeit nach Locale notwendig • Haben wir selbst gebaut auf Basis von Assetic, ist (noch) nicht Open-Source
  21. Und dann ... fingen wir an das JavaScript für den

    IE zu "optimieren" ... ... aber das ist eine andere, längere Geschichte.