Share
Embed
Transcript
32 slides
-
Worum geht's? • Bestandsaufnahme • Zielsetzung • Evaluierung • Konzept
/ Umsetzung • Lesson Learned -
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 -
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) -
trivago Technik • PHP 5.3 / JavaScript / Java /
C / Bash • FreeBSD • Apache / Percona / Memcache / Redis • Diverse CDN Provider • Direkte Level 3 / NTT Anbindung -
• 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" -
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, ...) -
• 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 -
Zend Framework 2 • Performance- Overhead ~60ms • Wenig Dokumentation
• Unklare API Stabilität, da Beta Kontrahenten Flow 3 • Performance- Overhead ~300ms • Akzeptable Dokumentation -
Symfony 2 • Performance Overhead ~60ms • Akzeptable Dokumentation •
2.0 mit mehreren Patch-Releases • Bonus: Bisherige Architektur Planung passt gut in das Symfony Konzept -
Cherry-Picking • Config / Routing / Event Dispatcher • HttpFoundation
• Service Container • Twig • Assetic -
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) -
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). -
• Components ◦ Keine Queries (Kosten / Nutzen) ◦ Keine
Entities (Dürfen keine Dependencies haben) • Services • Business Cases • Traits als alternativer Ansatz Service Container -
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 -
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 -
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. -
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 -
Beta Version • Konnte schon ein Bisschen mehr • First-byte
bei 600 - 700ms • Ajax Calls bei 400 - 460ms • Erster Live-Test in Frankreich -
• Mehrere AppKernels + eigenen AbstractAppKernel bringen Ordnung (und Performance)
• Konfigurationen mit mehr als 4 Environments sucken • addClassesToCompile() nutzen! Symfony 2 -
Twig • Autoescape abschalten. Händisch escapen +15% Performance • ext/Twig
nutzen! Twig's getAttribute ist teuer! • Macros vermeiden, besonders in Loops! -
Release Candidate • Funktionalität produktionsreif • First-byte bei ~300ms •
Ajax Calls bei < 200ms • Mehrere Live-Tests in Frankreich und Deutschland -
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 -
Und dann ... fingen wir an das JavaScript für den
IE zu "optimieren" ... ... aber das ist eine andere, längere Geschichte.