Tomcat – Clustering i Loadbalancing

Współczesne aplikacje internetowe są coraz bardziej skomplikowane i wymagaja coraz mocniejszych serwerów. Jednocześnie liczba użytkowników zwiększa się praktycznie z każdą minutą, co powoduje ze serwery muszą być jeszcze wydajniejsze. Można tej sytuacji zaradzić dokupując procesory, pamięci, zwiększając przepustowość kart sieciowych, jednakże w pewnym momencie trafimy na mur, którego już się w ten sposób obejść nie da. Możemy go jednakże przeskoczyć łącząc kilka komputerów w klaster, a następnie rozdzielając zapytania tak, aby wszystkie serwery były równo obciążone. Ta metoda jest również konieczna w przypadku, gdy awaria serwera jest niedopuszczalna i musimy zapewnić ciągły dostęp do aplikacji.
Tomcat
W trakcie normalnego działania klastra sesje są replikowane między wszystkimi komputerami przy użyciu jednej z następujących metod:
- Replikacja poprzez współdzielony sieciowy system plików (PersistanceManager + FileStore)
- Replikacja do bazy danych (PersistanceManager + JDBCStore)
- Replikacja w pamięci (SimpleTcpCluster)
Jeżeli jeden z Tomcatów ulegnie awarii jest usuwany z klastra a powiązane z nim zapytania są automatycznie przekierowywane przez loadbalancera. Sesje powiązane z uszkodzonym serwerem mogą zostac w zależności od konfiguracji wygaszone lub nie.
Przynależność do klastra jest określana przy pomocy pakietów UDP wysyłanych przez wszystkie Tomcaty, ze skonfigurowanym tym samym adresem multicastowym oraz portem. Replikacja sesji odbywa się przy użyciu pakietów TCP.
Zawór replikacji (ReplicationValve) służy do określenia kiedy zapytanie zostało zakończone i klaster może rozpocząć replikację.
Element w pliku server.xml konfiguruje domyślnie klaster z następującymi parametrami:
- Membership z adresem multicastowym 228.0.0.4 i portem udp 8012
- Potwierdzenie wysyłane co sekundę, usunięcie z listy po 30 sekundach bez odpowiedzi od danego Tomcata
- Odbiorca wiadomości SocketReplicationListener na domyślnym adresie IP oraz pierwszym wolnym portem z zakresu 8015 – 8019
- Replikacja oparta o ReplicationTransmitter w trybie fastasyncqueue
- Dodane ClusterSessionListener oraz ReplicationValve.
Wystarczy to do podstawowego skonfigurowania klastra, np. na maszynie developerskiej, jednakże w środowisku produkcyjnym zaleca się modyfikację ilości wątków obsługujących replikację i tryb replikacji.
Tipsy:
- Dokumentacja dotycząca klastrowania znajduje się tutaj: Tomcat 5.5, Tomcat 6.0
- Obiekty które są zapisywane w sesji muszą implementować java.io.Serializable (np. dto w kreatorach springowych)
- Na serwerach należy włączyć obsługę multicastu (np. pod Linuxem: ifconfig eth0 multicast)
- W web.xml powinien znajdować się element <distributable />, który powoduje, że dana aplikacja jest zdolna do działania w środowisku rozproszonym, czyli np. w klastrze.
- Najważniejszym elementem jeżeli chodzi o wydajność replikacji jest parametr replicationMode, konfigurowalny w elemencie <Sender …/>
Apache i mod_jk
Mod_jk to moduł do apache’a obsługujący komunikację z Tomcatem. Worker to instancja Tomcata na której uruchomione są servlety i do której przekierowywane są zapytania. Mod_jk jest konfigurowany, tak jak inne moduły, w pliku apache.conf lub httpd.conf. W niektórych dystrybucjach (np. debian) pliki konfiguracyjne modułów znajdują się w podkatalogu mods-enabled i są includowane w głownym pliku konfiguracyjnym.
Konfiguracja mod_jk
Moduł ładowany jest przy pomocy dyrektywy:
LoadModule jk_module ${sciezkaDoKataloguZModulami}/mod_jk.so
Następnie musimy dodać plik z workerami:
JkWorkersFile /etc/apache/workers.properties
Oczywiście plik workers.properties znajdować się może w dowolnym miejscu widocznym przez Apache’a.
Dodatkowo, należy też skonfigurować punkt montowania, czyli scieżkę od której przetwarzaniem zapytań zajmować będzie się Tomcat.
JkMount /* tomcat1
Ta dyrektywa sprawia, że wszystkie zapytania które odbierze Apache będą przekserowane do Wolkera o nazwie tomcat1. JkMount może się powtarzać i umieścić ją można zarówno w globalnej konfiguracji, VirtualHost jak i w Location (tylko nazwa workera, ścieżka będzie z Location) .
Zamiast montowania każdego punktu z osobna można użyć pliku uriworkermap.properties przy pomocy dyrektywy JkMountFile wskazującej na plik z mapowaniem.
Konfiguracja workera
Workery znajdują się przeważnie w pliku workers.properties. W pliku powinna znaleźć się dyrektywa worker.list oraz definicja co najmniej jednego workera. Worker.list to lista oddzielonych przecinkami workerów, które będą udostępnione mod_jk. Workera definiuję się w następujący sposób:
worker.nazwaWorkera.type= worker.nazwaWorkera.host= worker.nazwaWorkera.port=
Typ to najczęściej ajp13, który zastąpił starszy ajp12 i udostępnił między innymi kompresje danych i obsługę SSL’a.
Konfiguracja loadbalancera
Loadbalancer to specyficzny typ workera który nie komunikuje się z Tomcatem, tylko zajmuję się zarządzaniem pozostałymi „prawdziwymi” workerami, czyli min. rozdziela zadania na poszczególne instancje Tomcata używając algorytmu Round Robin z wagami. Sprawdza też które Tomcaty z listy nie odpowiadają i nie wysyła do nich zapytań.
Konfiguracja definiuję się w nastepujący sposób:
worker.nazwaWorkeraLB.balance_workers=
Dodatkowo można skonfigurować sticky session, czyli czy loadbalancer powinien przekierowywać zapytania z istniejącym sessionId do obsługującego je wcześniej Tomcata. Domyślnie ta funkcjonalność jest włączona.
Workerom można przyporządkować rózne wagi (worker.nazwaWorkera.lbfactor) a w loadbalancerze zmienić metodę wyboru workera do którego przekazane zostaną zapytania (worker.nazwaWorkeraLB.method). Do wyboru są następujące metody:
•R[equest] – kryterium jest obłożenie zapytaniami. Domyślne ustawienie.
•S[ession] – kryterium jest obłożenie sesjami. Zalecane w przypadku ograniczonych zasobów do obsługi sesji.
•B[usyness] – kryterium jest aktualne obciążenie serwera. Zalecane w przypadku długich sesji, np. w aplikacjach udostępniających pliki.
•T[raffic] – kryterium jest ilość ruchu na łączu między Apachem a Tomcatem. Zalecane w przypadku ograniczonej łączności między klasterm a Apachem.
Linki:
Przykłady
Apache -> mod_jk -> 1 tomcat
Najprostszy przykład. Zapytania są przekierowywane do jednego tomcata.
Konfiguracja Apache 1:
workers.properties:
worker.list=tomcat1 worker.tomcat1.type=ajp13 worker.tomcat1.host=10.1.1.2 worker.tomcat1.port=8009
Konfiguracja Tomcat1:
server.xml, sekcja Service:
<Connector port="8009" protocol="AJP/1.3" />
Apache -> mod_jk -> 2 tomcaty w klastrze
Najbardziej użyteczna według mnie konfiguracja, bez użycia balansowania DNS’owego lub sprzętowego. Balansowaniem zajmuje się mod_jk.
Konfiguracja Apache 1:
workers.properties:
worker.list=cluster worker.tomcat1.type=ajp13 worker.tomcat1.host=10.1.1.2 worker.tomcat1.port=8009 worker.tomcat2.type=ajp13 worker.tomcat2.host=10.1.1.3 worker.tomcat2.port=8009 worker.cluster.type=lb worker.cluster.balance_workers=tomcat1, tomcat2
Konfiguracja Tomcat’ów:
server.xml, sekcja Service:
<Connector port="8009" protocol="AJP/1.3" />
server.xml, sekcja Host:
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"/>
Dodatkowo, do należy dopisać jvmRoute=”${nazwaHosta}”, gdzie ${nazwaHosta} to odpowiednio tomcat1 i tomcat2
Apache -> mod_jk -> 1 tomcat jako loadbalancer -> 2 tomcaty w klastrze
Metoda ta używa aplikacji “balancer” uruchomionej na Tomcat’ie, który nie jest w klastrze. Zaletą tego rozwiązania jest możliwość dowolnego skonfigurowania balancingu. Wadą jest konieczność napisania klasy zajmującej się wyborem najlepszego Tomcata. Rozwiązanie to używa pliku workers.properties z przykładu pierwszego, konfiguracji klastra z przykładu drugiego oraz dodatkowego Tomcata, na którym działa aplikacja balancer. workers.properties przekierowuje zapytania na Tomcata pełniącego rolę LoadBalancera.








August 19th, 2008 at 12:23
“Ta metoda jest również konieczna w przypadku, gdy nie awaria serwera jest niedopuszczalna i musimy zapewnić ciągły dostęp do aplikacji.”
Tu chyba jest błąd – “nie awaria”
August 19th, 2008 at 14:23
Poprawione, dzieki ;)