Jak przyspieszyć działanie TYPO3 przy pomocy nginx'a.
UWAGA. Nowa wersja i nowa podstrona dedykowana tylko evo_nginx_boost techblog.evo.pl/evo_nginx_boost-extension/ Teraz evo_nginx_boot może pracować bez użycia NGINX'a. Wymagane jest TYPO3 i memcache!
TYPO3 cache
Kwestia wydajności TYPO3 była omawiana wiele razy. Znalazłem wiele różnych tricków, które pozwalają przyśpieszyć czas generacji strony między innymi moduł nc_staticfilecache czy dmc_highperformance. Najnowsza wersja TYPO3, która obecnie jest w fazie alpha radykalnie zmienia podejście do cachowania, dając nam do wyboru różne mechanizmy wsparcia jak file, memcache, database, czy apc.
Problem
Wszystkie powyższe rozwiązania z wyjątkiem nc_staticfilecache mają jedną wspólną rzecz: aby odczytać cache należy wywołać proces php i odczytać scachowane dane, sparsować, a następnie wysłać do przeglądarki.
Zróbmy prosty test z wykorzystaniem narzędzia ab. Sprawdzimy ilość zapytań na sekundę z wykorzystaniem złożonej witryny.
ab -n 100 -c 1 <a href="http://localhost/" >localhost</a> Server Software: Apache/2.2.6 Server Hostname: localhost Server Port: 80 Total transferred: 5064709 bytes HTML transferred: 5031914 bytes Requests per second: 1.02 [#/sec] (mean) Transfer rate: 50.66 [Kbytes/sec] received
Ilość zapytań na sekundę 1.02!
Co się stanie jeśli nasz serwis będzie musiał obsłużyć 1000 takich zapytań na sekundę? Nawet z najbardziej wydajnym mechanizmem cachowania, każde wywołanie parsera PHP do odczytania danych spowoduje bardzo duży load na serwerze.
Nginx
Z pomocą może nam przyjść serwer proxy NGINX. Nie jest on może nowym odkryciem, ale sprytne połączenie go z TYPO3 spowoduje wzrost wydajności ponad 200x! Opisane przeze mnie rozwiązanie obsługuje ruch użytkowników zalogowanych i niezalogowanych, uwzględnia zmianę strony po zalogowaniu oraz różne ustawienia cache w TYPO3.
Teraz do rzeczy. Oto założenia naszej instalacji:
Użytkownik wywołuje stronę. Nginx sprawdza jego cookie. Jeśli ustawione jest cookie o nazwie nginx_boost_noCache wtedy zapytanie jest wysyłane odrazu do Apacha a później do TYPO3 z pominięciem memcache. Dzięki temu cookie możemy łatwo kontrolować kiedy bezwzględnie należy wyłączyć cachowanie w memcache. Może to zrobić w dowolnej wtyczce w naszym systemie. Poniżej wyciąg z konfiguracji nginx do obsługi takiego przypadku
if ($http_cookie ~* "nginx_boost_noCache=1") { proxy_pass <a href="http://domain" >domain</a>; break; }
W sytuacji kiedy nginx nie znajdzie cookie nginx_boost_noCache, sprawdza czy w memcache istnieje scachowana strona. Jako klucz używa $request_uri.
# set default memcache key set $memcached_key $request_uri; # Check if local memcached server can answer this request default_type text/html; memcached_pass 192.168.168.3:11211;
Jeśli nasza strona nie znajduje się w memcache, nginx ponownie wysyła zapytanie do apacha. Apache wywołuje TYPO3, generuje stronę, następnie wtyczka evo_nginx_boost zapisuje ją do memcache z memcache_key takim samym jak żądany url.
$memcache_key = "domain/about-us"
Kolejne wywołanie tej strony zostanie wysłane odrazu z memcache bez potrzeby uruchamiania procesu PHP.
Nasza wtyczka w pełni uwzględnia ustawienia czasu cachowania w TYPO3 dla każdej ze stron, odcztuje też wartość cache_period. Jeśli w TYPO3 nie zostało nigdzie ustawiony czas cachowania to pobieramy wartość defaultową z konfiguracji wtyczki.
Co jeśli użytkownik się zaloguje?
Wszystko zależy od nas. Możemy w nginx i evo_nginx_boost wyłączyć zupełnie cachowanie dla zalogowanych. My jednak analizując nasze potrzeby i statystyki strony doszliśmy do wniosku, że zalogowany użytkownik często w ramach jednej sesji ogląda i wraca do tych samych stron. Zmiana musi nastąpić kiedy użytkownik wyśle żądanie POST, np: napisze komentarz, czy artykuł w blogu. W takiej sytuacji korzystamy z hooka w clasie class.tslib_fe.php - initFEuser.
Jeśli użytkownik się zaloguje ustawiamy cookie nginx_boost_fe_user o wartosci takiej samej jak fe_typo_user.
$memcache_key = "domain/blogs/us1b27c2c23bdb600912561e08a7e4886b"
Natomiast po wysłaniu POSTa lub innej operacji, która wymaga odświeżenia widoku dodajemy do tej wartości wersje. Wtyczka evo_nginx_boost następnie zapisuje do memcache nową wersję strony.
$memcache_key = "domain/blogs/us1b27c2c23bdb600912561e08a7e4886b_1"
Po 5min wersja strony się przedawni i nginx wyśle nowe żądanie do Apacha i Typo3. Jeśli w tym czasie inny użytkownik doda komentarz do bloga to zobaczymy to po 5min.
Warto też ustawiać małe czasy cachowania dla stron w których dane są często zmieniane. W serwisie społecznościowym o dużym obciążeniu widok strony usuwamy z cache co 1-5min to spokojnie nam wystarczy do obsłużenia bardzo dużego ruchu.
Teraz czas na testy ab dla powyższego rozwiązania.
ab -n 100 -c 1 <a href="http://localhost/" >localhost</a> Server Software: nginx/0.6.35 Server Hostname: localhost Server Port: 80 Total transferred: 10103800 bytes HTML transferred: 10089200 bytes Requests per second: 400.05 [#/sec] (mean) Transfer rate: 39468.58 [Kbytes/sec] received
Ilość zapytań na sekundę 400.05!
Opis konfiguracji evo_nginx_boost
Property: | Data type: | Description: | Default: |
|---|---|---|---|
enable | string | enable disable memcaching | 1 |
forceTimeoutToAllPages | int | set default memcache expiration time (has priority over TYPO3 setting) | 0 |
disableCacheForLoogedUsers | int | enable/disable memcaching for logged users | 0 |
cleanOnClearAllCache | int | if set, memcache is cleared when backend user click clear cache | |
setPageCacheTimeout OverrideAllTypoSettings | int | if you enable this option, you can override all expires time from your user_int extension, fg if you have page with four extensions and each extension calls static function: if (method_exists('tx_evo_nginx_boost', 'setPageCacheTimeout') tx_evo_nginx_boost::setPageCacheTimeout($timeout); evo_nginx_boost set expire time to the lowest value set in all 4 plugins | 1 |
_mainServerIP | string | memcache server ip | |
_mainServerPort | string | memcache server port | |
_mainServerPersistent | int | enable persistant connection | 1 |
_mainServerTimeout | string | memcache server connection timeout | 1 |
memcacheSignature | int | add signature to end o pages | 1 |
memcacheSignatureText | string | text of signature fg "CACHED BY ME :)". If you set memcacheSignature = 1 time of expiration is added to the end of memcacheSignatureText | 1 |
excludedUrls | array | Set in ext_localconf. This is array of urls which should be excluded from memcaching. Let say you have confirmation message after successfuly saving post in user's blog. Page with message "your post was saved" will be memcached. You can add parameter message=1 and put this in array. Evo_nginx_boost exclude this url from memcaching. | 1 |
Wtyczka posiada również moduł BE, w którym możemy obserwować wszystkie parametry związane z serwerem memcache. W opcji cachedump można sprawdzić jakie strony z jakim memcache key zostały zapisane:
Całe rozwiązanie było testowane na bardzo skomplikowanej witrynie z dużą ilością różnych rozszerzeń USER i USER_INT. Czekamy na uwagi i sugestie.
Pliki do pobrania:
- konfiguracja nginxa nginx.conf
- wtyczka typo3 evo_ngix_boost
- server nginx można pobrać ze strony nginx.net
Uwaga:
Wersja nginxa dostępna przez apt-get w dystrybucji ubunt 8.04.1 posiada błąd.
Bugfix: a segmentation fault occurred in worker process, if the "memcached_pass" and "if" directives were used in the same location.
Należy pamiętać, aby czas serwera był taki sam jeśli nginx i apache są na różnych maszynach :)



Najnowsze komentarze
Powered by Disqus