Download - Skalowalność Magento - MMPL13
Piotr Karwatka, Divante
Skalowalność Magento – teoria i trochę praktyki
Skąd się tu wziąłem?
• Z Wrocławia • Divante wdraża Magento• Byłem CTO Divante
– „Byłem” może być mylące – nadal pracuję w Divante,– Brałem udział jako programista oraz architekt kilku
sporych sklepów• Jestem bardzo zainteresowany skalowalnością i
wysoką wydajnością– Stworzyliśmy system CDN SimpleStorage.pl– … oraz kilka innych ambitnych projektów ;-)
O czym opowiem?
• O skalowalności w ogóle; O skalowalności Magento– Najpierw trochę teorii – czym jest
skalowalność, skalowalność sprzętu, aplikacji, bazy danych, storage, action-plan
– Potem trochę praktyki – case skomplikowanego serwisu: EAV, indexy, cache, replikacja, pomiary i optymalizację
Teoria
Skalowalność jest ważnaWeb 1.0 – read, Web 2.0 – read & write-Serwisy post web 2.0 “nie wiedzą” kiedy i z jakim impetem ich treści zostaną rozbudowane,-Serwisy e-Commerce muszą być przygotowane na nagłe wzrosty użytkowników (święta, nadzwyczaj udane promocje, reklamy TV …)
Wnioski?-Musimy być przygotowanina niespodziewane-Niewystarczająca skalowalność to wymierne straty
źródło: blogs.akamai.com
Wysoka dostępnośćIle czasu w miesiącu aplikacja może nie działać?
Poprawa skalowalności bywa katalizatorem zwiększenia dostępności,bo wykorzystuje wspólne metody działania:-Procesowe podejście (procedury, testy),-Podejście architekturalne i podział na warstwy,-Analizy i testy przed podejmowaniem decyzji,-Monitoring, wykrywanie wąskich gardeł, profilowanie-Redundancję (zwielokrotnienie) sprzętu – replikacja, modele N+1, 2N …
sieć
hardware (serwery, dyski…)
software (app + db)
Przyczyny: - dobra architektura jest droga? - „pomyślimy o tym, gdy stanie się problemem” (za późno!), - zwiększanie skalowalności “na szybko” jest bardzo ryzykowne - pomiary, testy i szukanie rozwiązań zajmuje sporo czasu - korzystamy z gotowych, „profesjonalnych” rozwiązań!
Wnioski: - dobra architektura całego systemu to podstawa, - kluczowy jest podział na warstwy, choćby wirtualny, - badaj i mierz dokładnie gdzie występuje problem, - skaluj tylko te warstwy, gdzie występuje problem
Dlaczego istnieje problem?większość oprogramowania jest
źle zaprojektowana
Dobra wiadomość: Architektura Magento jest OK!
middlewaremiddleware
cachecache
storagestorage
aplikacjaaplikacja
baza danychbaza danych
Skalowanie aplikacji jest proste- Konfiguracja środowiska (najprostsze): używaj byte-code’u (w
PHP -> APC, XCache), menedżera procesów FPM (pamięć, lepsze wykorzystanie APC),
- Monitoruj serwery i sprawdzaj aplikację automatycznie (Icinga,
Collectd, New Relic …)
- wykrywaj wcześnie wąskie gardła - najczęściej dostęp do danych
i I/O: New Relic, htop, iotop, collectd,
- używaj cache'u aby je zlikwidować (Redis(!), memcached)
- to jest pierwszy krok.
optymalizuj / profiluj
Skalowanie aplikacji jest proste...Skalowanie aplikacji na poziomie sprzętu
- pionowe - więcej RAM’u, lepsze CPU -> szybko docieramy do granic, drogie!
- ale pomoże bez żadnych zmian w aplikacji
- poziome – więcej tanich serwerów -> nie ma granic (w teorii!)
- ale też ew. problemy ze stanem sesji,
trudniejsza konfiguracja, trudniejsze zarządzanie (phing, pupet…?)
- większa dostępność aplikacji (n+1, 2n ...)
- darmowe loadbalancery na poziomie aplikacji (Perlball, Nginx jako proxy, odchudzony Apache jako proxy, .. serwer DNS?), - sprzętowe (Cisco!) lepsze ale droższe, sporo droższe.
koszt
ilość cpu
Skalowanie aplikacji jest proste...
...
+ =
Co wybrać? Oto rebus
Skaluj pionowo dopóki możesz, potem skaluj poziomo
Skalowanie aplikacji jest proste...Gotowe rozwiązania – Oktawave, OVH PC, e24cloud, EC2, Azure...
+ nie wymagają opieki nad własnym środowiskiem sprzętowym,
+ łatwe w konfiguracji i zarządzaniu (zarządzanie obrazami systemów),
+ przezroczysta obsługa wielu centrów danych – odporność na awarie,
+ tanie przy małych i średnich projektach (kilka centów za godzinę pracy),
+ odporność na skoki (+ autoskalery)!
- ale drogie przy dużych rozwiązaniach,
- skalowanie tylko aplikacji oraz storage
(+prosta replikacja bazy danych)
wirtualizacja środowiska, elastyczne chmury obliczeniowe
http://www.spidersweb.pl/2013/03/autoskaler-oktawave-wykop-efekt.html
Skalowanie aplikacji jest proste...
... ale bazy danych nie!- rdbms to najczęstsze wąskie gardło – połączenia, req/s,
- nie ma jednego – właściwego rozwiązania a naprawdę skalowalne
rozwiązania są trudne!
Unikaj skomplikowanych rozwiązań póki to możliwe:
1) Przechwytuj wolne kwerendy i je optymalizuj
- używaj profilowania i EXPLAIN (mysql)
- optymalizuj strukturę (indeksy, denormalizacja jeśli potrzebna),
2) Używaj cache na poziomie dostępu do danych
(nie cache.. tylko memcached!)
Cache jest łatwy w skalowaniu
cache
db
SELECT ..... FROM ...Hit - 90%
Miss - 10%
Skalowanie aplikacji jest proste...
... ale bazy danych nie!Replikacja – odporność na awarie, szybkość dostępu
+ wiele punktów dostępu do danych – większe req/s i odporność na awarie
Zyski:
+ aplikacja która dużo czyta, mało pisze:
- aplikacja która dużo czyta i dużo pisze:
- opóźnienia replikacji, - sesje użytkowników
+ tworzenie wyspecjalizowanych serwerów DB
(kilka tabel, wyszukiwanie...),
master slave
master
mastermaster
master
master
master
TB: users
TB: photos
:-(
:-)
Skalowanie aplikacji jest proste...
... ale bazy danych nie!Partycjonowanie – skalowanie poziome bazy danych
Partycjonowanie pionowe Partycjonowanie poziome - federacja
- różne tabele na różnych hostach,- prosta implementacja (replikacja),- szybko dochodzimy do ściany
- podział ogromnej tabeli pomiędzy różne serwery,- umożliwia tworzenie user-clusterów- bardzo dobre zrównoważenie zapisów i odczytów,- nigdy nie dochodzimy do ściany
Table
Table
Table
Table
A - F
G - O
P - Z
A - ZTableTable
A - Z
A - ZA - Z
Table 1
23
Table
A - Z4
.... Table3 JOIN Table2 ???
... WHERE Table.Imie = 'Alfons' AND Table.Imie = 'Zenon' ???
A co z moimi fotkami? ”Jeden nginx znaczy więcej niż 1000 Apachy”
- wydziel serwery dla treści statycznych (static.serwis.pl?) - dla fotek, CSS, JS ...
Pliki użytkowników szybko rosną?1) RAID (0, 01...)
2) NAS – (NetApp FAS?) – stosunkowo drogie, bardzo szybkie, automatyczne kopie, rozmiary powyżej 500TB,
3) Clustered File Systems (GlusterFS, CEPH, MogileFS, odłamki NFS/SMB/FTP) – automatyczna replikacja na wielu serwerach, odporność na problemy, szybkość przy szybkiej sieci,
4) CDN (Akamai ...) – serwujesz 300 tys. strumieni wideo na raz?
5) CloudFront – pod warunkiem, że serwis jest „na świat” - stosunkowo wolny, tani przy małych i średnich ilościach danych, drogi przy duuużej skali!
One rosną jeszcze szybciej!
Skalować nieskalowalne
• Systemy zewnętrzne (ERP) to duży problem• Dostępność jest kluczowa (zagubione zamówienia)• Niewiele możemy zrobić, ale możemy ustawić się w
kolejce (Gearman, Beanstalkd, ApacheMQ, RabbitMQ)
Kolejki pomagają skalować to co nieskalowalne
+
Jak się przeskalować?o ile to możliwe, projektuj z myślą o skalowaniu poziomym,
Krok 1-skaluj pionowo dokąd tylko się da:-optymalizuj to co wykorzystuje wąskie gardła,-korzystaj z Cache gdzie tylko można,-umieść bazę danych na osobnym serwerze
Krok 2-wydziel serwery dla obrazków i plików statycznych,-dodaj kolejne serwery aplikacji,-stwórz klaster cache,- stosuj serwery storage – a jeśli to za mało twórzklastry rozproszonego systemu plików-zastosuj serwery reverse proxy (Varnish)
Krok 3-skaluj bazę danych korzystając z replikacji,-... ale dąż do skalowania poziomego o ile to możliwe
rosnące koszty
++
+
+
+ ...
..
.
++ +
proxy
wwwsql memcache storage
......
Praktyka
Nietypowy problem
• e-Commerce na Magento + kilka integracji (CRM, ERP, WMS …)
• ilość produktów 37 800• Jednoczesnych, aktywnych użytkowników – 200-250 –
sesje do kilku godzin(!)• ilość atrybutów ~ 5500 (!) (nie można zastosować flat)• ilość attribute-setów ~ 1561• Ilość zapytań WebServices (integracje) / dobę – ok 100
000• Charakterystyka ruchu – dużo zapisów (zapytania
ofertowe, kompletowanie koszyków), dużo odczytów
Pierwsze podejście
• Cache dla bloczków (memcached),• EAV jest wolny - włączmy flat (nie da się przy tylu atrybutach),• Mieliśmy już w miarę wolny od podstawowych błędów wydajności
kod (dzięki http://www.slideshare.net/ivanchepurnyi/making-magento-flying-like-a-rocket-a-set-of-valuable-tips-for-developers
• Osobny serwer bazy danych (to będzie proste!) + replikacja (master-master backup),
• Dyski SSD (db + app), dużo RAM (16GB / serwer) – skalowanie pionowe,
• Tuning MySQL (bufory IO, bufory InnoDB), • Tuning Apache (limity użytkowników, FPM)
Do pewnego momentu było dobrze!
Większa ilość jednoczesnych użytkowników i zwiększającasię baza produktów wyeskalowały problem z szybkością
Co zrobiliśmy?
Profiluj, optymalizuj• Collectd zainstalowany na serwerach app + db – wykryliśmy po kolei
wąskie gardła – obciążenie IO, lockowanie bazy danych przy indeksowanie produktów
• Logi – diagnoza czasów odpowiedzi web-services i kolejek – logujemy czasy i trace wszystkich wywołań
• htop, iotop – przy „przytykaniu się serwisu” mogą służyć do szybkiego sprawdzenia co generuje problem
• Xdebug - na serwerach testowych badaliśmy
• Profiler – badanie ilości kwerend, czasu generowania bloków (wykrywanie miejsc pod użycie cache)
• JMeter, siege – do testowania obciążenia aplikacji
• New Relic – analiza szybkości aplikacji, można znaleźć wolne kwerendy i znaleźć gdzie dokładnie występują także na serwerach produkcyjnych
Infrastruktura
• Wysoka dostępność jest kluczowa – model 2N
master masteraplikacja + klaster GlusterFSoba serwery mogą obsługiwać ruch
Haproxy – load balancerdocelowo też reverse-proxy (Varnish)
Aplikacja i cache• Redis jest szybszy niż memcached jako backend cache• Warto skorzystać z Varnisha (z ESI) do plików statycznych i page caching
(http://www.magentocommerce.com/magento-connect/pagecache-powered-by-varnish.html)
• Load balancing przez HAProxy (w trybie automatycznego przepinania failover)• Dodaliśmy cache w Mage_Catalog_Model_Product::load
– Ale warto też dodać cache do Mage_Eav_Model_Entity_Abstract aby ominąć mechanizm EAV – przy dużej liczbie atrybutów nie można użyć FLAT
• Na 900 atrybutów najczęściej używanych ustawiliśmy FLAT – na więcej nie mogliśmy (ograniczenie InnoDB),
• Sesje warto przenieść w 100% do REDIS/Memcached (ale wtedy z replikacją) – dość mocno obciążają bazę danych – wydzielenie ich do cache rozwiązuje problem sticky sessions
• core_url_rewrite również generuje dużo zapytań i warto dodać cache w tym miejscu• Dodaliśmy cache do wykonanych/modyfikowanych przez nas bloków HTML i
sprawdziliśmy czy działa• Zastosowaliśmy moduł „Fast-Async Reindexing” aby uniknąć lockowania bazy danych
przy indeksowaniu atrybutów
Aplikacja i cache
• Pułapki– Trzeba uważać na GlusterFS/inne systemy plików
sieciowych (może działać szybko – funkcje stat(), open()) – również logi
– APC nie działa 100% stabilnie w PHP 5.4 (zdarzały nam się segfaulty) – w nowszych wersjach Opcache
– Warto rozważyć użycie nginx + php-fpm zamiast Apache (zużycie RAM, szybkość, stabilność) - http://info.magento.com/rs/magentocommerce/images/MagentoECG-PoweringMagentowithNgnixandPHP-FPM.pdf)
Proste rozwiązania się skończyły
Baza danych• Największy problem to EAV oraz indeksowanie,
– marzymy o FLAT w nierelacyjnej bazie danych (MongoDB, SOLR search ..)
– na razie posiłkujemy się cache na modelach,
• Wyłączyliśmy logi i statystyki (raporty) Magento – dużo zapisów, dużo danych które nie były potrzebne
• Wymieniliśmy bazę danych na PerconaDB/XtraDB,– dużo większa odporność na obciążenie –
ilość kwerend vs. response time – nawet do 275%,
– transparentne przejście (100% zgodność z MySQL)
• MemSQL wygląda świetnie – mało rozpowszechniony i komercyjny, przyglądamy się
Baza danych
– Tunining• innodb_buffer_pool_size - powinien być większy niż
rozmiar bazy danych• query_cache_limit - ostrożnie – 5MB; tylko dla krótkich
powtarzalnych kwerend wystarczy, • query_cache_size - czyszczenie cache może być bardzo
wolne powyżej 128MB• innodb_thread_concurrency – warto ustawić na 0
(dowolna ilość wątków)
Baza danych
• Bez FLAT – bardzo dużo zapytań EAV, również dużo zapytań odnośnie przekierowań URL. Te kwerendy są niepotrzebne.
Jak się pozbyć EAV?• Jeśli FLAT (kategorie + produkty minimum) jest zbyt wolny lub nie można go włączyć
– to bardzo kusi skierowanie się w stronę nierelacyjnej bazy danych (np. MongoDB, SOLR search, Sphinx Search …)– nadpisanie indekserów EAV->FLAT jest ekstremalnie trudne (relacje, niektóre moduły operują na języku SQL)– wg. naszych badań najprościej:
• cache na Product::load – ważna inwalidacja (chociażby data modyfikacji w kluczu cache lub observer),
• cache na ładowanie atrybutów EAV – karta produktu, szczegóły produktu na liście
• nadpisanie modeli w Mage_Catalog - przeglądanie i wyszukiwanie (częściowo zrobione z użyciem FactFinder) – kwerendy i filtrowanie
• Polecam: http://www.solvingmagento.com/magento-eav-system/
Baza danych• Planujemy wykorzystanie replikacji master-slave aby uniknąć
lagów sieciowych i locków związanych z indeksowaniem• Magento wspiera taką replikację out-of-box,• Teoretycznie powinno zmniejszyć response-time
bazy danych (testy potwierdzają)
master masteraplikacja + klaster GlusterFSlokalne db-slave do szybkich odczytówoba serwery mogą obsługiwać ruch
Haproxy – load balancerdocelowo też reverse-proxy (Varnish)
Indeksowanie,aktualizacje,Importy – na serwerach master
Indeksowanie magento odbywa się w PHP: lock -> logika -> unlock
Indeksowanie vs. replikacja• Replikacja master-slave
powinna pomóc przy lockowaniu – Magento rozpoczyna transakcję, wykonuje logikę i dopiero odblokowuje wiersz (Mage_Index_Model_Indexer)
• MySQL replikuje same operacje zapisu (UPDATE/INSERT/DELTE) przez binlog – te operacje są bardzo szybkie
public function processEntityAction(Varien_Object $entity, $entityType, $eventType)... $resourceModel = Mage::getResourceSingleton('index/process'); $resourceModel->beginTransaction(); $this->_allowTableChanges = false; try { $this->indexEvent($event); $resourceModel->commit(); } catch (Exception $e) { $resourceModel->rollBack(); if ($allowTableChanges) { $this->_allowTableChanges = true; $this->_changeKeyStatus(true); $this->_currentEvent = null; } throw $e; } if ($allowTableChanges) { $this->_allowTableChanges = true; $this->_changeKeyStatus(true); $this->_currentEvent = null; } $event->save(); Mage::dispatchEvent('end_process_event' . $this->_getEventTypeName($entityType, $eventType)); }
Storage
• Kod aplikacji na dyskach SSD (deployment via SVN/GIT) – szybsze interpretowanie, duża ilość plików PHP / 1 request + APC
• Pliki synchronizowane między serwerami za pomocą GlusterFS – rozproszony system plików, teoretycznie możliwość dodawania dowolnej ilości serwerów aplikacji, rozwiązuje problem z uploadem
• GlusterFS jest w porządku– POSIX,
– Nie trzeba synchronizować dużych ilości meta-danych
– Wszystkie dane w normalnych plikach (ważne w przypadku awarii!)
– Mirroring w trybie active-active
– Multiprotocol-client (my korzystamy z GlusterFS native)
• Tutaj właściwie nie ma nic ciekawego, wszystko zrobił Admin
Integracje• Wąskie gardła omijamy przez
kolejkowanie,
• Na każdym serwerze aplikacji uruchomione workery kolejek Gearman (procesy PHP) – pobieranie cen, przekazywanie zamówień – wszystko trafia do kolejek
– Ważne jest logowanie wszystkiego – workery działają w tle
• Workery wymieniają się danymi z CRM, WMS, ERP w trybie async i sync, możliwe priorytety
• Workery mogą być bezpiecznie resetowane, dowolny serwer app może obsługiwać dowolne zadania,
• Wzorzec Command/Task
# Reverse Client Code$client= new GearmanClient();$client->addServer();print $client->do("reverse", "Hello World!");
$worker= new GearmanWorker();$worker->addServer();$worker->addFunction("reverse", "my_reverse_function");while ($worker->work()); function my_reverse_function($job){ return strrev($job->workload());}
client
worker
Integracje
• Nigdy nie można ufać temu co jest po drugiej stronie
• Gearman wymusił też dobrą architekturę kodu odpowiedzialnego za integracje
• U nas przetwarza ponad 100 000 req/dobę i działa bardzo stabilnie
Chcesz zajmować się optymalizacją i skalowalnością Magento?
Szukamy doświadczonych developerów – napisz na [email protected]
Dziękuję za uwagę!
Więcej o skalowalności?Znajdziesz w naszej książce. Także o wysokiej dostępności,bezpieczeństwie i prowadzeniuprojektów
Dostępna na helion.pl