$30 off During Our Annual Pro Sale. View Details »

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. Heavy Lifting
    trivago goes Symfony

    View Slide

  2. Intro
    Foto: probe.ch / flickr

    View Slide

  3. Mario Müller

    View Slide

  4. Worum geht's?
    ● Bestandsaufnahme
    ● Zielsetzung
    ● Evaluierung
    ● Konzept / Umsetzung
    ● Lesson Learned

    View Slide

  5. View Slide

  6. 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

    View Slide

  7. 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)

    View Slide

  8. trivago Technik
    ● PHP 5.3 / JavaScript / Java / C / Bash
    ● FreeBSD
    ● Apache / Percona / Memcache / Redis
    ● Diverse CDN Provider
    ● Direkte Level 3 / NTT Anbindung

    View Slide

  9. Foto: (c) ibikenz / flickr

    View Slide

  10. ● 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"

    View Slide

  11. 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, ...)

    View Slide

  12. Evaluierung

    View Slide

  13. ● 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

    View Slide

  14. Zend Framework 2
    ● Performance-
    Overhead ~60ms
    ● Wenig
    Dokumentation
    ● Unklare API
    Stabilität, da Beta
    Kontrahenten
    Flow 3
    ● Performance-
    Overhead ~300ms
    ● Akzeptable
    Dokumentation

    View Slide

  15. Symfony 2
    ● Performance Overhead ~60ms
    ● Akzeptable Dokumentation
    ● 2.0 mit mehreren Patch-Releases
    ● Bonus: Bisherige Architektur Planung passt
    gut in das Symfony Konzept

    View Slide

  16. Cherry-Picking
    ● Config / Routing / Event Dispatcher
    ● HttpFoundation
    ● Service Container
    ● Twig
    ● Assetic

    View Slide

  17. 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)

    View Slide

  18. Architektur

    View Slide

  19. 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).

    View Slide

  20. ● Components
    ○ Keine Queries (Kosten / Nutzen)
    ○ Keine Entities (Dürfen keine Dependencies haben)
    ● Services
    ● Business Cases
    ● Traits als alternativer Ansatz
    Service Container

    View Slide

  21. 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

    View Slide

  22. Unsere "Evolution"

    View Slide

  23. 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

    View Slide

  24. 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.

    View Slide

  25. 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

    View Slide

  26. Beta Version
    ● Konnte schon ein Bisschen mehr
    ● First-byte bei 600 - 700ms
    ● Ajax Calls bei 400 - 460ms
    ● Erster Live-Test in Frankreich

    View Slide

  27. ● Mehrere AppKernels + eigenen
    AbstractAppKernel bringen Ordnung (und
    Performance)
    ● Konfigurationen mit mehr als 4
    Environments sucken
    ● addClassesToCompile() nutzen!
    Symfony 2

    View Slide

  28. Twig
    ● Autoescape abschalten. Händisch escapen
    +15% Performance
    ● ext/Twig nutzen! Twig's getAttribute ist teuer!
    ● Macros vermeiden, besonders in Loops!

    View Slide

  29. Release Candidate
    ● Funktionalität produktionsreif
    ● First-byte bei ~300ms
    ● Ajax Calls bei < 200ms
    ● Mehrere Live-Tests in Frankreich und
    Deutschland

    View Slide

  30. 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

    View Slide

  31. Und dann ...
    fingen wir an das
    JavaScript für den IE
    zu "optimieren" ...
    ... aber das ist eine
    andere, längere
    Geschichte.

    View Slide

  32. Vielen Dank

    View Slide