Optymalizacja aplikacji społecznościowej na Facebook i Grono w praktyce

Jak sprawić, aby aplikacja społecznościowa na Facebooku czy Gronie odwiedzana prawie milion razy miesięcznie działała bez problemów? Dowiesz się o tym z tego postu. Przedstawiam w nim techniki, które pozwoliły mi uzyskać taką wydajność na przykładzie aplikacji Quizzy.

Aplikacja Quizzy to 4 najpopularniejsza aplikacja online dostępna na stronie internetowej Grono.net. Grono.net (15) to pierszy polski serwis społecznościowy z 1,5 milionem real userów według najnowszego Megapanelu i jedyny polski konkurent Facebooka (14), który pozwala pisać aplikacje niezależnym programistom. Optymalizacja aplikacji społecznościowej nie różni się od tego na który serwis będziesz ją pisał.

Najlepszy sposób na optymalizację kodu programu

Aplikacja ma 71 200 użytkowników, dziennie 8 000 unikalnych użytkowników. Od zeszłego miesiąca kiedy wystartowała miała 880 000 odsłon. Dla porównania: to więcej niż miał Kominek w 2007 roku i 2,3 razy więcej niż ma Antyweb.

Dlaczego istnieje problem wydajności?

Problem wydajności aplikacji był spowodowany tym, że nie wszystkie polecenia były wykonywane na czas. Jeżeli założymy, że 400 osób używa jednocześnie aplikacji. Dla uproszczenia można przyjąć, że każda z nich wysyła w tym samym momencie prośbę do serwera o wyświetlenie strony aplikacji. Dopuszczalny w ekstremalnym wypadku czas czekania przez użytkownika na odpowiedź to powiedzmy 3 sekundy. 400 jednoczesnych requestów do serwera www musi być wykonanych w tym czasie. Oznacza to, że średnio request musi być zrealizowany w 3 / 400 sekundy czyli 8 milisekund.

Aplikację musiałem przedtem 2 czy 3 razy wycofać, ponieważ nie wytrzymywała obciążenia. Ale nie skończę tego tekstu na chwaleniu się, że udało mi się zoptymalizować serwer i aplikację pod takie obciążenie. Zamiast tego podzielę się z Wami konkretnymi optymalizacjami jakie zrobiłem, abyście mogli też je zastosować.

Optymalizacja sprzętu

Aplikacja początkowo miała do dyspozycji całego VPS-a w postaci OpenVZ z 512 MB RAM-u i 30% procesora 800Mhz. Po pierwszej próbie kiedy serwer padł w peaku o 17.00 postanowiłem zapewnić większą moc i dałem aplikacji trochę na wyrost 100% procesora 2,6 Ghz i 2 GB RAM. Jednak samo wzmocnienie sprzętu jest niczym gdy aplikacja jest nieoptymalna. Dlatego nie poprzestałem na tym.

Czytaj podobne  Programiści społecznościowi stawiają na rozrywkę

Optymalizacja bazy danych

Po pierwsze polecenie TOP (trywialne, ale od czegoś trzeba zacząć) pokazało, że proces mysqld zarzyna serwer. Okazało się, że zapytania które wykonywałem do bazy danych były ekstremalnie nieoptymalne. Do znalezienia ich przydał się slow query log. Listuje on najmniej wydajne zapytania do pliku tekstowego. Do optymalizacji przydało się polecenie explain. Główne optymalizacje polegały na odpowiednim stworzeniu indeksów w odpowiedzi na wyniki polecenia explain, które wskazało takie rzeźnickie praktyki jak „using filesort”.

Optymalizacja warstwy danych

Oprócz tego pozostała optymalizacja zapytań, ale tutaj roboty dużo nie było: przede wszystkim grupowanie po kolumnie występującej w tabeli użytej w left joinie okazało się bardzo nieoptymalne (1000 ms zmniejszone do 85 ms). Lepiej używać odpowiedniej kolumny w tabeli głównej.

Druga sprawa to filtrowanie danych określonej listy użytkowników. Wygląda na to, że lepiej listę użytkowników z API Grona umieścić w tabeli tymczasowej zamiast używać listy w zapytaniu w części select * from where in (1,2,3).

Optymalizacja dostępu do danych i wyników pośrednich

Obojętnie jak bardzo zoptymalizujemy bazę danych to nie wystarczy przy tej skali. Potrzebny jest zawsze kesz. W celu przechowywania wygenerowanych raz danych użyłem Memcached. Jest to system keszowania używany i polecany twórcom aplikacji przez Facebooka. Na pierwszym poziomie użyłem go do keszowania wyników zapytań SQL a na drugim do keszowania fragmentów i całych podstron które generowałem. Odciążyło to bazę danych na tyle, aby nie ubijała serwera. Teraz na przykład ściana Quizzów wyświetla się w 1,2 ms i używając 1 zapytania SQL. Zresztą nie jest ono też potrzebne – czas ten spadłby wtedy do ułamków milisekundy.

Czytaj podobne  Ranking polskich aplikacji społecznościowych

Warto też przed optymalizacją znaleźć najczęściej odświeżane strony aplikacji i je optymalizować, ponieważ optymalizacja działów rzadko odwiedzanych nie jest opłacalna.

Optymalizacja ustawień serwera WWW i bazy danych

Następnie wprowadziłem optymalizacje ustawień mysql i php. Najważniejszą optymalizacją było włączenie Fast CGI w postaci mod_fastcgi. Nie znam się na Linuxie i nie wiem czy to standard, ale na moim VPSie był serwer lighttpd ale z normalnym cgi, które nie ma według mnie racji bytu. Odkrycie, że problem wydajności leżał w interpretacji php wynikło z takiej próby: zrobiłem prosty plik php zliczający czas jego wykonania a obok drugi plik ale html. Czas wyświetlenia pustego php był o wiele większy niż html-a. W powyższym linku jest przykład sprawdzenia jakie moduły php masz włączone w konsoli. Do tego samego posłużyć może też phpinfo.

Niektóre poradniki wykazują też, że lepiej użyć lighttpd, ngx albo apache (niepotrzebne skreślić). Jednak różnice wydajności są tak znikome nawet przy tej skali jaką mają Quizzy, że mogą jedynie być przedmiotem dyskusji akademickiej.

Do szukania bugów i złodziei czasu w PHP przydatne jest Xdebug i wizualna nakładka Webgrind. Pozwalają one zdiagnozować które miejsce w kodzie trwa najdłużej i najczęściej będą to odwołania do bazy danych albo do API serwisu społecznościowego. Warto przy okazji pamiętać o keszowaniu tych drugich też.

Jeżeli mowa o wizualizacji to przydatny jest też plik memcached.php z PECL-owej wersji Memcached, który jednak działa na każdej innej wersji memcached i pokazuje użycie pamięci (nieduże) i inne ciekawe statystyki.

Czytaj podobne  Twórz gry online na Facebooku dzięki Online FB Games API

Akceleracja PHP

Podobny zresztą wizualizator ma APC, czyli pakiet do keszowania kodu pośredniego PHP (opcode). Optymalizacja kodu pośredniego daje najlepsze efekty, kiedy aplikacja webowa ma wiele skryptów, które używa. Do tej grupy zaliczają się wszystkie CMS-y jak Drupal gdzie wydajność PHP wzrasta 3 razy. W przypadku małych aplikacji webowych z małą ilością plików i kodu takich spektakularnych efektów się nie uzyska. Oprócz APC istnieje też eAccelerator, ionCube, MMCache, Xcache i Zend Optymizer. Niestety nie udało mi się dobrze zainstalować eAcceleratora i Xcache, Zend Optimizer sprawiał też problemy. APC zaskoczył od razu. Wszystkie wymienione akceleratory PHP działają na tej samej zasadzie co ujawnia się w tym, że różnice w ich wydajności również nie są istotne przy skali aplikacji jaką są Quizzy.

Podsumowanie

Po wszystkich optymalizacjach aplikacja i serwer działają bez przerwy od miesiąca i 2 tygodni. Nie zanotowałem żadnych problemów. Podsumowując nisko wiszące owoce optymalizacji to: indeksy, optymalizacja zapytań, memcached i fast cgi. Okazało się, że do takiej skali jaką mają Quizzy nie potrzeba wdrażać wszystkich technik z tej przeszło 100 slajdowej prezentacji. Na szczęście wbrew radom niektórych osób nie musiałem też zmieniać języka programowania. Okazało się, że PHP potrafi sobie radzić całkiem nieźle przy tej skali. Obecnie mój serwer większą część dnia śpi, czasem zużywając max. 5% mocy procesora. Niedługo jednak ten nadmiar zostanie odpowiednio spożytkowany.

Przeczytaj też

Programowanie gier społecznościowych na Facebooka ... W czym pisać kod gry? W PHP czy w JS? No i gdzie trzymać dane o rozgrywce i grach? Dowiedz się! W poprzednich częściach omówiłem kwestię wyboru ser...
Programowanie RMSBG na Facebooka cz. 5 – host gry... Kim jest host gry i czy powinien znajdować się na serwerze czy powinien nim być jeden z graczy? W poprzednich częściach ustaliliśmy środowiska prog...
Programowanie RMSBG na Facebooka cz. 4 – typ... Jakie typy komunikacji trzeba uwzględnić w pisaniu gry RMSBG? W poprzednich częściach założyliśmy, że robimy grę planszową RMSBG (Realtime Multipla...
Programowanie RMSBG na Facebooka cz. 3 – kom... Jak klient w JS może komunikować się z serwerem w PHP przez HTTP? W poprzednich częściach omówiłem rozwiązania klienckie i serwerowe dla gier RMSBG...
Programowanie RMSBG na Facebooka cz. 2 – Jęz... Jakie języki programowania trzeba znać, żeby pisać RMSBG na Facebooka? Dowiedz się. W poprzedniej części poruszyłem temat decyzji czy aby napisać R...
Napisano w Społecznościowe Tagi: , , , , , , , ,
One comment on “Optymalizacja aplikacji społecznościowej na Facebook i Grono w praktyce
  1. syllepsa pisze:

    Ciekawy wpis. Mimo, iż nie używam PHP.