Tag Archive: clustering


Zmiana pracy

Trochę było cicho przez ostatni miesiąc, ale był ku temu dobry powód. Zgadzam się z pierwszą tezą Boba McWhirtera: “Employment is good“. Zmieniłem pracę. Pracuję w JBoss, a division of Red Hat. Wspólnie z Bobem będziemy starali się stworzyć możliwie najprostsze w użyciu środowisko do klastrowania serwera aplikacji JBoss AS dla różnych platform wirtualizacyjnych: KVM, VMware, EC2, kto wie co jeszcze :) Naszym celem jest klaster gotowy do użycia, prosto z pudełka, bez zbędnych fajerwerków, po prostu działający. Co Ty na nim uruchomisz — Twoja sprawa, my dostarczymy Ci stabilne środowisko. Szczegółowe informacje będą pojawiały się na bieżąco na stronie skupiającej projekty pod kierownictwem Boba, gdzie wkrótce zacznę pisać artykuły na temat JBoss Cloud.

Dowiedz się również więcej na temat JBoss Rails (tak tak, aplikacje napisane w Rails działają na JBoss AS) i JBoss Cloud z wywiadu na DZone!

Cóż więcej mogę dodać — trzymajcie kciuki za nas!

Dostępne rozwiązania równoważenia obciążenia dla aplikacji napisanych w Javie praktycznie ograniczają się do kilku modułów do serwera HTTP Apache. Nie, nie twierdzę, że rozwiązanie jest złe! Powiedziałbym wręcz przeciwnie — serwer ten ma ugruntowaną pozycję na rynku, jest stabilny, a co najważniejsze — jest darmowy! Są oczywiście rozwiązania sprzętowe (np. urządzenia oferowane przez loadbalancer.org), jednak, co tu dużo mówić — ich cena jest dosyć zniechęcająca…

Jak to było do tej pory?

Podstawowym modułem serwera Apache obsługującym połączenia na linii Apache — serwer aplikacji był (a w zasadzie nadal jest) moduł mod_proxy (wraz z modułami zależnymi przeznaczonymi dla konkretnego protokołu np. AJP, HTTP). Jego konfiguracja jest naprawdę bardzo prosta. Mając raz utworzony plik konfiguracyjny można go wykorzystać w innych instalacjach zmieniając tylko potrzebne opcje. Dodatkowo, jeżeli skonfiguruje się moduł mod_proxy_balancer (domyślny sposób równoważenia obciążenia w serwerze Apache — pisałem o tym  wcześniej), otrzymujemy możliwość zdefiniowania wielu serwerów aplikacji, jak i zasad równoważenia obciążenia między nimi. Po szczegóły odsyłam do (krótkiej, ale konkretnej) dokumentacji. Dodatkowo w Internecie można znaleźć tony instrukcji w jaki sposób uruchomić load balancer na podstawie serwera Apache na wybranej dystrybucji Linuksa (uruchamia to ktoś na Windowsie?!). Rozwiązanie oparte na mod_proxy i mod_proxy_balancer jest naprawdę dobre, ale głupie. Moduły nie wiedzą nic o stanie serwerów aplikacji poza tym, czy działają :) Na ogół takie postawienie sytuacji powinno wystarczyć. Jednak w przypadku gdybyśmy chcieli obciążać tylko jeden serwer, a drugi traktować jako dodatkową moc obliczeniową wykorzystywaną tylko i wyłącznie w przypadku, gdy pierwszy serwer nie jest w stanie obsłużyć wszystkich zapytań, rozwiązanie oparte na mod_proxy_balancer nie będzie pomocne.

Z pomocą nadchodzi mod_cluster

Od początku listopada tego roku na stronach społeczności JBossa udostępniony został projekt pod kierownictwem Jean-Frederic Clerea o dumnej nazwie mod_cluster. Oprócz niego w projekcie uczestniczą Brian Stansberry oraz Paul Ferraro.  Zadaniem mod_cluster, zupełnie tak jak w przypadku mod_proxy, jest przekierowywanie zapytań z serwera Apache do serwerów aplikacji. W takim razie, czym różnią się te rozwiązania? W odróżnieniu od mod_proxy, w przypadku mod_cluster komunikacja jest dwukierunkowa. Serwer aplikacji dodatkowo nawiązuje połączenie z serwerem Apache. Właśnie to połączenie odpowiada za inteligencję tego rozwiązania. Za jego pomocą przekazywane są informacje z cyklem życia aplikacji, jak również inne informacje potrzebne do zarządzania load balancerem (np. aktualne obciążenie serwera aplikacji). Informacje przesyłane są za pomocą protokołu Mod-Cluster Management Protocol (MCMP), który w rzeczywistości jest zbiorem metod protokołu HTTP. Co ciekawe — nie jest wymagane utworzenie nowego gniazda dla tych połączeń — serwer aplikacji komunikuje się z serwerem Apache na porcie, na którym jest on skonfigurowany! W rzeczywistości mod_cluster nie jest pojedynczym modułem. Jest to raczej zbiór następujących modułów: mod_slotmem, mod_manager, mod_proxy_cluster oraz mod_advertise. Duża część kodu źródłowego jest oparta na aktualnych implementacjach mod_proxy. Co ciekawe, to konfiguracja po stronie serwera aplikacji odpowiedzialna jest za mapowanie odpowiednich adresów do aplikacji. Szczególny wpływ ma na to konfiguracja domeny i ścieżki danej aplikacji na serwerze aplikacji. Dane te są przesyłane za pomocą wiadomości CONFIG do wszystkich load balancerów.  Jeżeli przychodzące do serwera Apache zapytanie dla wybranej domeny i ścieżki zostanie odnalezione wśród wpisów posiadanych przez moduł mod_cluster, zapytanie to zostanie automatycznie przekierowane do wybranego węzła.

Wymagania

Aby móc uruchomić mod_cluster potrzebny jest serwer Apache w wersji powyżej 2.2.8. Niestety aktualna wersja httpd dostępna dla systemu Red Hat / CentOS 5.2 oznaczona jest numerem 2.2.3. Pozostaje skompilować samemu odpowiednie moduły z dostępnego kodu źródłowego, gdy chcemy wykorzystać standardową instalację demona httpd. Należy zwrócić uwagę, że deweloperzy przygotowali odpowiednie paczki dla wielu systemów operacyjnych zawierające całą potrzebną instalację (łącznie z serwerem Apache!). Wszystko jest kompletne, skonfigurowane i gotowe do użytku! Można to lepiej zrobić?

Do uruchomienia mod_cluster potrzebny jest również odpowiedni kontener. W grę wchodzi JBoss Application Server 5.0.0+, Apache Tomcat, oraz JBoss Web 2.1.1+. Niestety nie doszukałem się informacji z jakimi wersjami Apache działa mod_cluster.

Najważniejsze cechy mod_cluster

Rozwiązanie JBossa wprowadza wiele usprawnień wpływających na konfigurację i zarządzanie klastrem. Oto niektóre z nich.

Dynamiczna konfiguracja workerów (a po polsku?)

Do tej pory to load balancer musiał wiedzieć jakie serwery aplikacji wchodzą w skład klastra. Powodowało to potrzebę rekonfiguracji load balancerów przy dodawaniu nowego węzła w klastrze. Od tej pory, przy użyci mod_cluster, to serwery aplikacji będą posiadały informację o dostępnych load balancerach. Informacja ta może być umieszczona na stałe w konfiguracji serwerów aplikacji jako lista lub mogą one zostać wykryte automatycznie przez serwer aplikacji przy użyciu muticastu za pośrednictwem mechanizmu advertise. W środowiskach, w których nie można użyć multicastu (np. VMware) należy skonfigurować ręcznie listę dostępnych load balancerów.

Współczynnik obciążenia obliczany po stronie serwerów aplikacyjnych

Współczynniki rozkładu obciążenia w przypadku mod_proxy_balancer (jak i w starym mod_jk) były umieszczane na stałe w konfiguracji tych modułów. Statyczna konfiguracja mogła doprowadzić do przeciążenia jednego serwera, gdy inne w klastrze nie były obciążone. Oczywiście zależało to od poprawnego zdefiniowania współczynników. W przypadku mod_cluster problem ten został wyeliminowany. Współczynniki są obliczane po stronie serwerów aplikacji a następnie przekazywane do load balancera, który znając współczynniki wszystkich węzłów w klastrze może efektywnie zarządzać zapytaniami w zależności od obciążenia serwerów.

Należy dodać, że rozwiązanie to sugeruje się informacjami otrzymanymi od serwerów — po stronie serwera http nie ma obliczania współczynników!

Pełna kontrola cyklu życia aplikacji

Rozwiązania dostępne obecnie na rynku w postaci modułów serwera Apache nie potrafią poprawnie obsłużyć takich zdarzeń jak wdrożenie, czy usunięcie aplikacji z serwera. Odwołanie się do usuniętej z serwera aplikacji powoduje po prostu wyświetlenie błędu 404. W przypadku mod_cluster błędy te zostały wyeliminowane, ponieważ informacje o cyklu życia aplikacji są przesyłane do load balancera.

Architektura mod_cluster

Architekturę mod_cluster można podzielić na dwie części. Z jednej strony znajdują się usługi uruchomione na serwerze http, z drugiej strony usługi uruchomione na serwerze aplikacji. Po stronie serwera http uruchomiony jest zestaw modułów wspomnianych wcześniej, natomiast po stronie serwera aplikacji uruchomiona jest usługa ModClusterService. Usługa ta odpowiedzialna jest za komunikację z dostępnymi load balancerami. W szczególności dotyczy to informowania ich o stanie serwera i aplikacji na nim uruchomionych. Szczegółowe informacje można znaleźć na stronach wiki projektu.

Wyróżnić można dwa tryby pracy klastra: z klastrowaniem lub bez.

Konfiguracja bez klastrowania

W tym trybie serwery aplikacji nie wymieniają danych między sobą.

Konfiguracja bez klastrowania

Konfiguracja bez klastrowania

Oznacza to, że dwie, te same, aplikacje uruchomione na dwóch serwerach nie będą wiedziały o swoim istnieniu, oraz żadne dane nie będą replikowane do innych serwerów. Klient, po awarii jednego z serwerów i przełączeniu do innego, straci wszystkie dane znajdujące się aktualnie sesji, będzie się musiał również ponownie zalogować. Oczywiście przesyłane są informacje do serwera http odpowiedzialne za rejestrację serwera apliakcji w load balancerze, czy związane z cyklem życia aplikacji. Natomiast współczynnik obciążenia przesyłany przez serwer aplikacji będzie miał wartość obliczaną (lub ustalaną odgórnie) tylko dla tego konkretnego serwera. Współczynnik ten będzie wpływał na działanie całego systemu tak samo jak wartość lbfactor w pliku konfiguracyjnym workers.properties modułu mod_jk.

Konfiguracja z klastrowaniem

W tym trybie serwery aplikacji formułują klaster, a dane są wymieniane między węzłami w klastrze.

Konfiguracja z klastrowaniem

Konfiguracja z klastrowaniem

Wymieniane są również informacje o aktualnym stanie serwerów pomiędzy instancjami. Jedna z usług ModClusterService będzie zawierała komponent HASingleton odpowiedzialny za zbieranie informacji o stanie wszystkich węzłów. Następnie dane te są poddawane analizie, a wyniki w postaci czynnika obciążenia dostarczane są wszystkim węzłom w klastrze oraz dostępnym load balancerom.

Instalacja

Należy skonfigurować odpowiednio serwer Apache i aplikacji. Bardzo dobra dokumentacja instalacji znajduje się na stronach mod_cluster, zarówno jeżeli chodzi o konfigurację serwera Apache jak i serwera aplikacji.

Podsumowanie

Pewnie parę osób zarzuci mi, że jestem przesadnie podekscytowany tym rozwiązaniem. Być może, ale nie ulega żadnej wątpliwości, że mod_cluster zmieni całkowicie podejście do programowych load balancerów. Polecam przyjrzenie się temu projektowi! Według mapy wydań możemy się spodziewać w najbliższym czasie pierwszego, stabilnego wydania mod_cluster, a więc nie ma na co czekać, tylko uruchamiać. W końcu każdy chce mieć stabilny i szybki system. Co? Może nie?

Warto odwiedzić

W pierwszej części napisałem czym jest klastrowanie i do czego służy. Pora skupić się na architekturach klastrowania dostępnych w serwerze JBoss AS.

Topografia klastra zdefiniowana w odpowiednim pliku konfiguracyjnym usługi HAPartition za pomocą XMLa dla każdej instancji, ma ogromne znaczenie dla administratorów serwerów JBoss. Programiści natomiast zwracają większą uwagę na konfigurację z punktu widzenia klienta usługi. W JBoss AS wykorzystywane są dwie architektury klastrowania:

  1. interceptory po stronie klienta,
  2. zewnętrzne loadbalancery.

Interceptory po stronie klienta

Większość zdalnych usług udostępniania przez serwer JBoss AS włączając w to JNDI , EJB, JMS , RMI czy JBoss Remoting wymaga od klienta, aby ten uzyskał (znalazł i pobrał) obiekt stub (proxy). Obiekt stub jest generowany przez serwer. Implementuje on interfejs biznesowy usługi. Po pobraniu obiektu stub przez klienta wywołuje on na nim lokalne zapytanie, następnie stub przekazuje zapytanie przez sieć do odpowiedniej usługi.

Architektura z interceptorem po stronie klienta

Architektura z interceptorem po stronie klienta

Zaślepka wygenerowana przez serwer zawiera w sobie interceptor, który wie jak rutować zapytania do wielu węzłów w klastrze. Następnie stub znajduje odpowiedni węzeł, serializuje parametry zapytania, odserializowuje wyniki zapytania i zwraca je do klienta. Interceptor posiada aktualną wiedzę na temat klastra. Zna on adresy IP każdego dostępnego węzła w klastrze, algorytm dystrybucji obciążenia pomiędzy węzłami oraz informację, w jaki sposób radzić sobie z sytuacją, gdy docelowy węzeł nie będzie dostępny.

W przypadku gdy topologia klastra zmienia się, węzeł uaktualnia dane w interceptorze przy najbliższym zapytaniu. Przykładowo, gdy jeden z węzłów zostanie odłączony od klastra – każdy interceptor zostanie o tym powiadomiony przy podłączeniu się do któregokolwiek aktywnego węzła. Wszystkie aktualizacje obiektu stub są niewidoczne dla klienta.

Polityki rozkładu obciążenia

Dla architektury opartej na interceptorach po stronie klienta serwer JBoss AS 4.2 oferuje następujące polityki:

  • Round-Robin (org.jboss.ha.framework.interfaces.RoundRobin) – każde zapytanie jest przekazywane do kolejnego serwera znajdującego się na liście dostępnych węzłów, pierwszy cel jest wybierany przypadkowo.
  • Random-Robin (org.jboss.ha.framework.interfaces.RandomRobin) – dla każdego zapytania docelowy węzeł wybierany jest przypadkowo.
  • First Available (org.jboss.ha.framework.interfaces.FirstAvailable) – jeden z dostępnych węzłów zostaje zostaje wybrany jako domyślny (bez znaczenia który). Gdy lista dostępnych węzłów zmieni się stub wybierze następny dostępny węzeł, jednak dopiero wtedy gdy wybrany wcześniej węzeł już nie działa. Każdy stub wybiera cel niezależnie. Jeżeli klient pobierze dwa obiekty stub (np. EJB) – każdy z nich wybierze samodzielnie cel. Jest to polityka, która zapewnia tzw. session affinity (sticky sessions).
  • First Available Identical All Proxies (org.jboss.ha.framework.interfaces.FirstAvailableIdenticalAllProxies) – polega na tym samym co, First Available z tą różnicą, że wszystkie zapytania jednego klienta będą kierowane do tego samego docelowego węzła. Dla przykładu: jeżeli klient pobierze dwa obiekty stub jakiejś usługi, każdy z nich będzie odwoływał się do tego samego węzła w klastrze.

Wszystkie powyższe polityki są implementacją interfejsu org.jboss.ha.framework.interfaces.LoadBalancePolicy. Można stworzyć również własną implementację tego interfejsu.

Loadbalancer

Wiele usług udostępnianych przez serwer JBoss nie wymaga od klienta, aby ten pobierał obiekt proxy. W szczególności dotyczy to usług związanych z protokołem HTTP, gdzie klient (często przeglądarka internetowa) wysyła zapytania i otrzymuje odpowiedzi bezpośrednio za pomocą połączenia odpowiedniego dla wybranego protokołu (np. HTTP). W takim przypadku wymagany jest zewnętrzny loadbalancer, którego zadaniem jest przetworzenie otrzymanych zapytań, a następnie ich wysyłka do węzłów w klastrze. Loadbalancer jest logiczną częścią klastra, mimo to określa się go jako usługę zewnętrzną.

Architektura z loadbalancerem

Architektura z loadbalancerem

Loadbalancer może zostać zaimplementowany jako rozwiązanie programowe bądź sprzętowe. Wielu producentów oferuje bardzo zaawansowane rozwiązania sprzętowe. W rozwiązaniach programowych na wyróżnienie zasługują moduły serwera Apache. Do wersji 2.2 serwera Apache rolę loadbalancera dla serwerów aplikacyjnych Javy pełnił moduł mod_jk. Obecnie funkcjonalność ta jest dostarczana przez moduł mod_proxy_balancer.

Loadbalancer posiada zaimplementowany mechanizm, który umożliwia mu poznanie topologii klastra oraz zapewnia logikę rozkładu obciążenia pomiędzy węzłami czy detekcji niedziałających węzłów. Problemem przy takiej architekturze może być to, że loadbalancer sam w sobie może być powodem braku dostępu do aplikacji, ponieważ gdy loadbalancer przestanie odpowiadać – żaden klient nie dostanie się do aplikacji, dlatego też loadbalancer powinien być stale monitorowany aby zapewnić wysoką dostępność całego klastra. Bardzo często stosuje się redundancję loadbalancerów aby wykluczyć pojedynczy punkt awarii.

Na ostatnim, trzecim spotkaniu Silesia JUG, po prezentacji Łukasza Lipki na temat Mule ESB kilka osób zainteresowanych było możliwością uruchomienia Mule ESB w klastrze. Okazało się, że polityka klastrowania musi zostać zaimplementowana ręcznie przez programistów. Ciekawe, bo bez tego ESB chcące być postrzegane jako technologia dla biznesu musi posiadać możliwość klastrowania. Nie zgłębiając dalej tematu Mule ESB, zaintrygowany tematem, postanowiłem napisać jak to jest w przypadku serwera aplikacji, na którym pracuję na co dzień, czyli JBoss Application Server.

Klastrowanie? A co to tak właściwie jest?

Klastrowanie pozwala na uruchomienie aplikacji na wielu, pracujących równolegle serwerach przy serwowaniu pojedynczego widoku dla klienta. Obciążenie rozłożone jest na wszystkie serwery w klastrze. W przypadku, gdy jeden lub więcej węzłów zostanie wyłączonych (ulegnie awarii) – aplikacja nadal jest dostępna za sprawą pozostałych, działających serwerów. Dzięki łączeniu serwerów w klastry można zwiększać wydajność aplikacji poprzez zwykłe dodawanie kolejnych węzłów do klastra. Oprócz zwiększonej mocy obliczeniowej klastrowanie oferuje redundancję, która jest bardzo często wymaganiem dla bezawaryjnego działania dużych aplikacji.

JBoss Application Server posiada wbudowane mechanizmy klastrowania. Najprostszą metodą uruchomienia klastra z serwerów JBoss jest uruchomienie każdego z nich w tej samej sieci lokalnej w konfiguracji all (za pomocą polecenia run -c all). Każdy z serwerów samoczynnie wykryje pozostałe węzły, które razem sformułują klaster.

Reasumując: klastrowanie ma dwa podstawowe zadania:

  1. utrzymanie niezawodności systemu,
  2. zwiększenie wydajności aplikacji.

Definicja klastra

Klaster to zbiór węzłów komunikujących się ze sobą, pracujących razem w celu osiągnięcia wspólnego celu.

W klastrze serwerów aplikacji JBoss AS, zwanym również partycją, pojedynczy węzeł to jedna instancja serwera JBoss AS. Komunikacja między węzłami odbywa się za pomocą grupy bibliotek JGroups. JGroups Channels pozwala na śledzenie, kto znajduje się w klastrze oraz na niezawodną komunikację pomiędzy członkami klastra. Instancje JGroups Channels posiadające te same konfiguracje i jednakowe nazwy mają zdolność do dynamicznego wykrywania siebie nawzajem i formowania w grupy. To dlatego uruchomienie dwóch serwerów w tej samej sieci lokalnej poprzez wywołanie polecenia run -c all wystarcza aby sformułować klaster. Każdy z serwerów uruchomi kanał (channel) z tą samą, domyślną konfiguracją. W ten sposób węzły mogą się rozpoznać w sieci tworząc razem klaster. Węzły mogą być dynamicznie dodawane i usuwane z klastra w każdym momencie. Wystarczy uruchomić lub zatrzymać kanał, który skonfigurowany jest w ten sam sposób jak inne węzły w klastrze.

Reasumując: klaster JBoss jest zbiorem instancji serwerów JBoss AS, przy czym każda instancja posiada uruchomiony JGroups Channel skonfigurowany dokładnie w taki sam sposób jak inne instancje.

Na jednej instancji serwera JBoss AS uruchomione usługi mogą uruchomić swoje własne kanały. Przy standardowej konfiguracji serwera JBoss AS 4.2 cztery usługi uruchamiają swoje kanały. Są to:

  • usługa replikacji stanu sesji HTTP,
  • usługa replikacji stanu SFSB,
  • usługa cacheowania encji EJB 3.0,
  • oraz standardowa usługa klastrowania zwana HAPartition.

Poszczególne kanały rozróżnia się za pomocą nazw – różne kanały muszą posiadać różne nazwy, przy czym konfiguracja węzłów w poszczególnych kanałach musi być taka sama dla wszystkich instancji

Przykładowe formowanie się węzłów w partycje

Przykładowe formowanie się węzłów w partycje

danej usługi w klastrze, jednak różna dla usług uruchomionych na pojedynczej instancji. W przypadku uruchomienia przykładowo dwóch instancji serwerów JBoss AS za pomocą polecenia run -c all może wydawać się, że mamy jeden klaster złożony z dwóch węzłów. Ściśle mówiąc jest to nieprawda, ponieważ każda usługa tworzy swój własny klaster, w związku z czym otrzymujemy cztery klastry każdy po dwa węzły. Dla jednej sieci, nawet dla tej samej usługi możemy mieć wiele klastrów. Diagram przedstawia przykładową sieć serwerów JBoss podzieloną na trzy partycje. Taką konfigurację można szybko uzyskać edytując poszczególne pliki konfiguracyjne w odpowiednich instancjach serwerów.

W następnej części zostaną omówione architektury klastrów możliwe do utworzenia przez serwer JBoss AS.

Follow

Otrzymuj każdy nowy wpis na swoją skrzynkę e-mail.