2. 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 ;-)
3. 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ę
5. Skalowalność jest ważna
0 – read, Web 2.0 – read & write
y post web 2.0 “nie wiedzą” kiedy i z jakim impetem ich treści
aną rozbudowane,
y e-Commerce muszą być przygotowane na nagłe wzrosty
kowników (święta, nadzwyczaj udane promocje, reklamy TV …)
?
y być przygotowani
podziewane
tarczająca skalowalność
erne straty
źródło: blogs.akamai.com
6. Wysoka dostępność
Ile czasu w miesiącu aplikacja może nie działać?
sieć
hardware (serwery,
dyski…)
software (app + db)
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 …
7. Dlaczego istnieje problem?
większość oprogramowania jest
źle zaprojektowana
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
baza danych
baza danych
aplikacja
aplikacja
storage
storage
cache
cache
middleware
middleware
Dobra wiadomość: Architektura Magento jest OK!
8. 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),
optymalizuj / profiluj
-
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.
9. 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.
10. Skalowanie aplikacji jest proste...
koszt
40
Skalowanie
pionowe
30
20
Skalowanie poziome
10
0
ilość cpu
Co wybrać? Oto rebus
=
+
...
Skaluj pionowo dopóki możesz, potem skaluj poziomo
11. Skalowanie aplikacji jest proste...
Gotowe rozwiązania – Oktawave, OVH PC, e24cloud, EC2, Azure...
wirtualizacja środowiska, elastyczne chmury obliczeniowe
+ 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)
http://www.spidersweb.pl/2013/03/autoskaler-oktawave-wykop-efekt.html
12. 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),
cache
2) Używaj cache na poziomie dostępu do danych
(nie cache.. tylko memcached!)
Cache jest łatwy w skalowaniu
Hit - 90%
SELECT ..... FROM ...
Miss - 10%
db
13. 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
master
master
mast
er
slave
master
TB: users
master
master
TB: photos master
(kilka tabel, wyszukiwanie...),
14. Skalowanie aplikacji jest proste...
... ale bazy danych nie!
Partycjonowanie – skalowanie poziome bazy danych
Partycjonowanie pionowe
- różne tabele na różnych hostach,
- prosta implementacja (replikacja),
- szybko dochodzimy do ściany
T a b le 1
Partycjonowanie poziome - federacja
- 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
A-Z
A-Z
T a b le 3
T a b le 2
T a b le
A-F
A-Z
A-Z
T a b le
T a b le
G-O
T a b le 4
A-Z
T a b le
.... Table3 JOIN Table2 ???
... WHERE Table.Imie = 'Alfons'
AND Table.Imie = 'Zenon' ???
PZ
15. 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,
One rosną jeszcze szybciej!
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!
16. 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
17. 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órz
klastry rozproszonego systemu plików
-zastosuj serwery reverse proxy (Varnish)
+
rosnące
koszty
Krok 3
-skaluj bazę danych korzystając z replikacji,
-... ale dąż do skalowania poziomego o ile to możliwe
+
+
...
+
+
...
+
...
www
proxy
..
.
sql
memcache
storage
19. 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
20. 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/makingmagento-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)
21. Do pewnego momentu było
dobrze!
Większa ilość jednoczesnych użytkowników i zwiększająca
się baza produktów wyeskalowały problem z szybkością
23. 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
24. Infrastruktura
• Wysoka dostępność jest kluczowa – model 2N
aplikacja + klaster GlusterFS
oba serwery mogą obsługiwać ruch
Haproxy – load balancer
docelowo też reverse-proxy (Varnish)
master
master
25. 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-byvarnish.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
26. 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/Magen
toECG-PoweringMagentowithNgnixandPHP-FPM.pdf)
28. 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ę
29. 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)
30. Baza danych
•
Bez FLAT – bardzo dużo zapytań EAV, również dużo zapytań
odnośnie przekierowań URL. Te kwerendy są niepotrzebne.
31. 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/
32. 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,
Indeksowanie,
• Teoretycznie powinno zmniejszyć response-time
aktualizacje,
bazy danych (testy potwierdzają)
Importy – na
serwerach master
master
aplikacja + klaster GlusterFS
lokalne db-slave do szybkich odczytów
master
oba serwery mogą obsługiwać ruch
Haproxy – load balancer
docelowo też reverse-proxy (Varnish)
Indeksowanie magento odbywa się w PHP:
lock -> logika -> unlock
33. Indeksowanie vs. replikacja
•
Replikacja master-slave
powinna pomóc przy
lockowaniu – Magento
rozpoczyna transakcję,
wykonuje logikę i dopiero
odblokowuje wiersz
(Mage_Index_Model_Ind
exer)
•
MySQL replikuje same
operacje zapisu
(UPDATE/INSERT/DELT
E) 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));
}
34. 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
35. 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
client
# Reverse Client Code
$client= new GearmanClient();
$client->addServer();
print $client->do("reverse", "Hello
World!");
worker
$worker= new GearmanWorker();
$worker->addServer();
$worker->addFunction("reverse",
"my_reverse_function");
while ($worker->work());
function my_reverse_function($job)
{
return strrev($job->workload());
}
36. 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
37. Dziękuję za uwagę!
Więcej o skalowalności?
Znajdziesz w naszej książce.
Także o wysokiej dostępności,
bezpieczeństwie i prowadzeniu
projektów
Dostępna na helion.pl
Chcesz zajmować się optymalizacją i
skalowalnością Magento?
Szukamy doświadczonych developerów – napisz na
rekrutacja@divante.pl