Glassfish
Architektura Java EE
Warstwy
Na rysunku 1 przedstawiono dwie wielowarstwowe aplikacje Java EE podzielone na warstwy opisane w poniższej liście:
- Warstwa klienta (ang. client tier) pracująca na maszynie klienta.
- Warstwa sieci (ang. web tier) pracująca na serwerze Java EE.
- Warstwa logiki biznesowej (ang. business tier) pracująca na serwerze Java EE.
- Warstwa danych (ang. enterprise information system ? EIS tier) pracująca na serwerze bazy danych
Architektura wielowarstwowa
- Warstwa klienta może się składać z jednego, bądź też kilku z podanych rozwiązań:
- Klient webowy. Składa się z dynamicznej strony Web zbudowanej przy użyciu języków znaczników, takich jak HTML, czy XML oraz przeglądarki internetowej, która prezentuje dane otrzymane z serwera. Klienci tacy często nazywani są cienkimi klientami (ang. thin client) z uwagi na fakt, że nie wykonują oni z reguły złożonych zadań biznesowych, czy zapytań do baz danych. Operacje takie delegowane są przez nich do komponentów pracujących na serwerach Java EE
- Applet. Jest to mała aplikacja napisana w języku Java, która wykonywana jest na zainstalowanej w przeglądarce internetowej wirtualnej maszynie Java.
- Aplikacja kliencka. Uruchamiana jest ona na maszynie klienta i jak to widać na rysunku 2-2 komunikuje się bezpośrednio z komponentami logiki biznesowej z pominięciem warstwy sieci. Z reguły posiada graficzny interfejs użytkownika (ang. grafical user interface, GUI), co umożliwia wykonywanie zadań wymagających wykorzystania możliwości nie oferowanych przez przeglądarki internetowe. Aplikacje klienckie napisane w językach innych niż Java również mogą komunikować się z serwerami Java EE.
- JavaBeans. JavaBeans są to klasy posiadające pewne właściwości oraz metody get i set, które pozwalają te właściwości pobierać i ustawiać. Mogą one istnieć zarówno na poziomie klienta, jak i serwera. Wspomagają przepływ informacji pomiędzy aplikacja kliencką, serwerem oraz bazą danych.
- Warstwa sieci składa się z serwletów (ang. servlet) lub stron tworzonych za pomocą technologii JSP i/lub JSF. Serwlety są to klasy, które dynamicznie przetwarzają żądania (ang. requests) wysyłane przez przeglądarkę internetową do serwera i konstrują odpowiedzi (ang. responses). Strony JSP to dokumenty tekstowe, które w kodzie HTML umożliwiają wstawienie fragmentów języka JAVA. Kod taki przed wysłaniem do użytkownika jest przetwarzany przez serwer do postaci kodu HTML. Umożliwia to bardziej naturalne podejście do tworzenia statycznej treści niż w przypadku serwletów. JSF jest zbudowana na bazie serwletów i stron JSP, w pewnym sensie je łączy udostępniając interfejs użytkownika.
- Warstwa logiki biznesowej jest to miejsce, w którym tak na prawdę odbywa się przetwarzanie danych i rozwiązywanie problemów stawianych przed aplikacją, takich jak np. obliczenie ile klient danego banku ma jeszcze kredytu do spłaty. Rysunek 2-2 przedstawia jak warstwa logiki biznesowej odbiera informacje, jeżeli potrzeba przetwarza je i przekazuje do warstwy danych w celu ich zapisania. Warstwa ta pobiera też dane z warstwy danych i przekazuje je dalej w celu prezentacji klientowi.
- Warstwa danych - jej zadaniem jest odpowiednie utrwalenie przekazanych jej danych, oraz ich odczytanie i zwrócenie, gdy zostanie do niej wysłane odpowiednie żądanie.
Pomimo faktu, że aplikacje Java EE mogą zawierać trzy, lub cztery warstwy, tak jak to widać na rysunku 2-2 przyjęło się, że aplikacje Java EE są trzywarstwowe, z uwagi na fakt, że pracują one w trzech lokacjach: maszynie klienta, serwerze Java EE oraz serwerze bazy danych. Aplikacje trzywarstwowe pracujące w ten sposób rozwijają standardową architekturę dwuwarstwową poprzez dodanie wielowątkowego serwera aplikacji pomiędzy klientem a serwerem baz danych.
Komponenty
Aplikacje Java EE tworzone są z komponentów. Komponenty są to samowystarczalne jednostki oprogramowania dostarczające pewne funkcje i mające możliwość komunikowania się z innymi komponentami. Zawierają one w sobie odpowiednie klasy oraz wszelkie inne niezbędne pliki. Tworzą one pewnego rodzaju cegiełki, z których składa się aplikacje. Specyfikacja Java EE definiuje następujące komponenty:
- Aplikacje klienckie i aplety pracujące w warstwie prezentacji.
- Serwlety, JavaServer Faces (JSF) oraz JavaServer Pages (JSP) będące komponentami webowymi i pracujące na serwerze.
- Komponenty Enterprise JavaBeans (EJB), zwane też enterprise beans, będące komponentami biznesowymi pracującymi na serwerze.
Komponenty Java EE pisane są w języku JAVA i kompilowane są tak samo, jak wszystkie inne programy napisane w tym języku. Różnica pomiędzy komponentami Java EE, a standardowymi klasami Java polega na tym, że działają one i są zarządzane przez kontenery Java EE.
Wprowadzenie. Kilka słów o GlassFish
Serwer aplikacyjny dostępny od Sun Microsystems pierwotnie miał swe początki jako alians iPlanet (kooperacja inżynierów Sun Microsystems z NetScape). Po okresie wspólnej pracy z NetScape, Sun projekt iPlanet rozwijał pod swoimi skrzydłami już pod nazwą SunONE, Sun Open Net Environment. Nazwa ta została wprowadzona w 2002 roku i była przewidziana na grupę produktów, które powstały w wyniku aliansu. SunONE z kolei przekształcił się w linię produktów odpowiedzialnych za warstwę webową (serwer webowy, aplikacyjny, portal etc.) obecnych w ofercie pod nazwami Sun Java System. Debiut SJS nastąpił podczas konferencji SunNetwork we wrześniu 2003 roku. W ramach SJS powstał Sun Java System Application Server, który obecnie jest starą nazwą na wspierany serwer aplikacyjny oferowany od Sun Microsystems. Sun Java System Application Server v9.1 to ostatnia wersja z działu aplikacyjnych serwerów z nazwą SJSAS a jego odpowiednikiem (bit w bit identyczna implementacja, jedynie różny instalator i kilka graficznych plików) jest Sun GlassFish Enterprise Application Server
GlassFish a GlassFish Enterprise oraz historia wersji.
Serwer GlassFish jest dostępny w dwóch wersjach – OpenSource oraz Enterprise (http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-glassfish-419424.html). Mowa tu o GlassFish Application Server oraz GlassFish Enterprise Application Server. Obydwie wersie posiadają podobną implementację z tą różnicą, że Enterprise posiada oficjalny suport od strony Sun Microsystems, moduły do HADB oraz zestaw trzech, dodatkowych, płatnych narzędzi dostępnych w pakiecie Enterprise Manager – Performance Advisor, Performance Monitor oraz SNMP Monitor. Z uwagi na HADB będziemy pracować z wersją Enteprise. Rozwój każdej z edycji podzielony jest na 3 fazy:
- Concept Creation – zbieranie kluczowych wymogów, określanie ram czasowych, prototypowanie.
- Active Development – implementacja w kierunku Milestone aż do wersji finalnej.
- Maintenance – poprawki finalnej edycji, wydania produktu z poprawkami.
- Pierwszy GlassFish v1 miał swoja premierę w maju 2006 roku i jego odpowiednikiem w ofercie Sun’a był Sun Java System Application Server 9.0 PE. Był on implementacją specyfikacji JEE5, jednak z kilkoma brakami jak możliwość klastrowania. GlassFish v2 miał premierę we wrześniu 2007 roku wraz z wersją wspieraną przez Sun’a o nazwie Sun Java System Application Server 9.1. Te wersje wspierały już klaster, load balancing, jak również replikację sesji przez pamieć. Wersia SJSAS 9.1 wspierała HADB, która od kwietna 2008 roku zmieniła nazwę na GlassFish Enterprise v2.1. W grudniu 2009 otrzymała update do wersji v2.1.1 prezentujący drobne poprawki w produkcie.
Wersja v3 GlassFish’a dostępna od grudnia 2009 roku jest pierwszą w pełni zgodną implementacją serwera aplikacyjnego z JEE6. GlassFish v3 jest serwerem modułowym (bazując na OSGI, implementacja Apache Felix) w którym moduły instaluje się łącząc się przez telnet do DAS’a na port 6666. GlassFish v3 jest dostępny w dwóch profilach: WEB – Servlets, JSP, JavaBeans, POJO, oraz Full – Servlets, JSP, JavaBeans, POJO, EJB.
Suszona rybka. Wpierw trochę teorii.
W architekturze serwera aplikacyjnego GlassFish występuje kilka pojęć, które warto przypomnieć zanim zaczniemy pracę, abyśmy zrozumieli podstawowe słownictwo występujące podczas instalacji oraz konfiguracji naszego środowiska.
Domain Administration Server (DAS)
jest to centralny serwer w architekturze GlassFish’a
Poniżej mamy graficzną prezentację przykładowego środowiska, na którym będziemy pracować. W celu wyjaśnienia wszystkich elementów wchodzących w jego skład, kolejno opiszemy każdy z nich.
Przykładowa architektura. 1 domena, 1 DAS, 1 klaster, 4 agenty, 4 instancje.Całość działa na systemie Solaris.
- Domain Administration Server (DAS) - jest to centralny serwer w architekturze GlassFish’a. DAS to instancja administracyjna o nazwie server, odpowiadająca za centralny monitoring, logowanie, wdrażania aplikacji, konfiguracje zasobów dla klastrów i instancji, utworzonych w obrębie domeny. DAS jest miejscem, gdzie administrujemy domeną.
Uwaga: Zalecany rozmiar heap dla tego procesu to 512MB.
- Domena - z kolei jest to zbiór instancji, klastrów wchodzących w jej skład mających wspólną konfigurację i udostępnione zasoby w jej obrębie. Każda domena ma swego DAS’a (na którym trzymane jest centralne repozytorium aplikacji) oraz profil domeny, który określa jej możliwości. Jest on ustalany podczas jej tworzenia. Dostępne są trzy przedefiniowane profile: Developer, Cluster, Enterprise. Ostatni jako jedyny dostępny jest w wersji komercyjnej (GlassFish Enterprise) i jako jedyny ma wsparcie do HADB. Konfiguracja domeny jest całościowo przeprowadzana na DAS’ie i przechowywana w pliku domain.xml również na DAS’ie.
- Klaster - jest to nazwany zbiór homogenicznych instancji. Homogeniczność określana jest jedynie po wersji aplikacyjnego serwera. Każdy klaster istniejący w domenie (może być ich kilka) musi mieć unikatową nazwę. Jest tak ponieważ każdy klaster swą konfigurację przechowuje w katalogu, który ma nazwę określoną przez nazwę klastra. Każdy klaster należy zawsze i tylko do jednej domeny.
- Instacja - klastrowa (clustered instance) bądź nie (stand-alone instance) jest to działający proces GlassFish’a. Proces JVM hostujący aplikacje (będące kopią aplikacji z centralnego repozytorium w DAS). Na jednej instalacji GlassFish’a może działać kilka jego instancji, każda nasłuchująca na innych portach HTTP, HTTPS, JMX, oraz IIOP.
Raz stworzona instancja stand-alone nie może być później dodana do klastra.
Uwaga: Zalecany rozmiar heap dla pojedynczego procesu instancji to 512MB.
Instancje podobnie jak klastry, muszą mieć unikatową nazwę w obrębie domeny i należą zawsze i tylko do jednej domeny. Jest tak z uwagi na ich konfigurację, przechowywaną w odrębnych katalogach. Jakakolwiek komunikacja z instancją następuje poprzez agenta.
- Node Agent - jest to lekki proces uruchamiany ręcznie, lub skonfigurowany jako usługa w systemie operacyjnym (Windows 2000 - Service Contol, Windows XP i wyżej gotowy skrypt ma.cfg, Solaris do wersji 9 – init.d, Solaris 10 – usługa Service Management Facility), który odpowiada za komunikację oraz synchronizację instancji wchodzących w skład domeny z DAS’em (synchronizacje lokalnych repozytoriów z centralnym). Proces ten jest wymagany, aby móc zainstalować instancję. Jedyna instancja, która nie wymaga agenta to DAS.
Instalacja agenta jest jedyną czynnością jaką trzeba przeprowadzić na nowej maszynie w celu dodania jej do domeny GlassFish’a. Po jego instalacji dodawanie/instalacja instancji na nowej maszynie przeprowadzane jest zdalnie z DAS’a.
Proces agenta jest aktywny jedynie podczas cyklu życia instancji obsługiwanych przez niego (tworzenie, uruchamiania, usuwanie instancji, etc.).
HADB
GlassFish w swojej ofercie posiada dwa mechanizmy do przetrzymywania sesji. In-memory replication jako szybkość i opensource, oraz HADB, stabilność na wysoką skalę, wsparcie oraz replikacja JMS. Oba mechanizmy dają podstawową funkcjonalność – replikację sesji. Do przetrzymywania samej sesji in-memory replication ma przewagę wydajności (RAM) i jest lepszym rozwiązaniem na małą skalę. Jeśli jednak ilość naszych sesji przekracza (zależne od środowiska, aplikacji, zasobów i innych współczynników) 100000 aktywnych sesji, mechanizm HADB staje się niezastąpiony w przypadku tak dużego obciążenia. GlassFish w swojej ofercie posiada dwa mechanizmy do przetrzymywania sesji
- HADB, High Availiability Database jest to mechanizm rozproszonej bazy danych, której repozytoria są przechowywane w plikach na każdym z nodów. Baza HADB służy jako repozytorium sesji i wiadomości JMS, i przewidziana jest do dużych systemów, w których tolerancja utraty sesji oraz wysoka dostępność mają spełnić standardy 5 9’s (5 dziewiątek - czas niedostępności w roku <= 5 min, dostępność 99,999%).
Tyle teorii czas przejść do praktyki!
Pobieranie oraz instalacja GlassFish
GlassFish jest referencyjna implementacją Serwera Aplikacji dla platformy Java EE. Zawiera referencyjną implementację specyfikacji JPA. Ponad to jest otwarty, dystrybuowany za licencji CDDL, a część elementów na licencji GNU GPL v2.
Zanim zaczniemy używać GlassFisha należy pobrać go ze strony: http://glassfish.java.net/public/downloadsindex.html . Należy wybrać wersję przeznaczoną dla naszej platformy sprzętowej my wybieramy:
Open Source Distribution GlassFish Server Open Source Edition 3.1.2.2
A final and community release implementing the full Java EE 6 standard. Includes an extensible core based on OSGi, with Full Clustering, Centralized Admin, SSH or DCOM provisioning, High-Availability, improved Admin Console, Update Center, embedded API, and more. This is fix release for the GlassFish 3.x family with many component updates (Grizzly, Weld, Mojarra, Jersey, EclipseLink, OSGi, JavaDB, ...), JDK 7 support, AIX support and more.
Następnie pobieramy wersję wielojęzyczną dla Windows: glassfish-3.1.2.2-windows-ml.exe (multilingual)
Instalacja Serwera w środowisku Windows
Instalacja serwera w środowisku Windows przebiega zwykle brzproblemowo, pod warunkiem że sprzęt spełnia minimalne wymagania sprzętowe oraz porty na których działają komponenty nie są już używane. Przy instalacji na Windows 7 należy uruchamiać instalatora z menu kontekstowego (Uruchom jako Administrator)
Administracja serwerem
Serwer Glassfish może być administrowany na dwa sposoby. Pierwszy z nich to administracja przez program asadmin. Drugi sposób to administracja przez stronę www.
Program asadmin
Administracja za pomocą konsolowego programu asadmin jest dość skomplikowana i wymaga dużej cierpliwości. Wystarczy tylko wspomnieć, że sam manual dostępny w trybie tekstowym ma 22 strony. Dlatego też na razie pominę szczegółowy opis tego sposobu. Należy jednak wspomnieć o kilku bardzo istotnych opcjach, które osiągalne są tylko z poziomu programu konsolowego.
Uruchomienie i zatrzymanie serwera
Uruchomienie Glassfish'a jest możliwe tylko z poziomu konsoli. Program do administracji przez www jest zwykłą aplikacją web i nie może posłużyć do uruchomienia serwera. Uruchomienie i zatrzymanie serwera omówione zostało już w rozdziale Uruchamianie serwera. Należy wspomnieć, że można rozłożyć ten proces na dwa etapy. W pierwszym za pomocą polecenia konsoli asadmin uruchamiam program administracyjny, a następnie wpisujemy:
C:\glassfish3\bin\asadmin start-domain domain1
i uruchamiamy serwer.
UWAGA: domain1 oznacza nazwę domeny którą chcemy uruchomić.
Podobnie sprawa ma się ze zatrzymywaniem serwera, w tym celu wywołujemy komendę:
C:\glassfish3\bin\asadmin stop-domain domain1
Serwer zatrzymać możemy też za pomocą aplikacji www. Uruchomienie serwera z poziomu www jest z oczywistych względów niemożliwe.
Inne przydatne polecenia
Domeny
pomoc asadmin help
start serwera bazy danych derby asadmin start-database
lista domen asadmin list-domains
usunięcie domeny asadmin delete-domain domain8
backup domeny asadmin backup-domain domain8
zmiana hasła administratora asadmin change-admin-password
zmiana hasła głównego asadmin change-master-password
przywrócenie domeny z backupu asadmin restore-domain --filename /opt/backups/glassfish_backup_v00001.zip domain8
weryfikacja pliku konf. domain.xml asadmin verify-domain-xml
usunięcie zdefiniowanego połączenia asadmin delete-jdbc-connection-pool sample-mysql-pool
Konnektory JDBC
utworzenie połączenia JDBC asadmin create-jdbc-resource --connectionpoolid sample-mysql-pool \ --host 127.0.0.1 --port 4849 --secure --user admin \jdbc/sample-jdbc-resource
usunięcie połączenia JDBC asadmin delete-jdbc-resource jdbc/sample-jdbc-resource
lista połączeń JDBC asadmin list-jdbc-connection-pools
lista zasobów JDBC asadmin list-jdbc-resources
Klastry
lista klastrów asadmin list-clusters
usunięcie klastra asadmin delete-cluster cluster01
uruchomienie klastra asadmin start-cluster cluster01
zatzrymanie klastra asadmin stop-cluster cluster01
Node agents
lista node agentów asadmin list-node-agents
usunięcie node agenta asadmin delete-node-agent nodeAgent1
zatrzymanie node agenta asadmin stop-node-agent nodeAgent1
Panel www
W celu ułatwienia zarządzania serwerem powstała specjalna aplikacja www, która pozwala na pełną kontrolę działań serwera. Jedynymi ograniczeniami jest zatrzymanie i uruchomienie serwera.
Logowanie do panelu admina
W trakcie uruchamiania serwera zostaje też uruchomiona aplikacja służąca do administrowania serwerem z poziomu strony www. Jeżeli chcemy się do niej dostać należy w przeglądarce wpisać adres http://localhost:4848/ Ukaże się wtedy taki widok:
Po podaniu danych (domyślne):
Login: admin
Password: adminadmin
ukaże się nam główna strona aplikacji administracyjnej:
Jak widać możliwe działania obejmują proces wdrażania aplikacji JEE, modułów EJB, aplikacji web, monitorowanie stanu serwera, przeglądanie logów, konfigurację źródeł danych i web services. Można też przejść do różnych podręczników zamieszczonych na stronie firmy Sun
Przegląd opcji
Z racji, że panel www dla wersji Enterprise oraz Open Source wygląda prawie tak samo, do demonstracji użyjemy jednego z nich (Enterprise), natomiast w późniejszym czasie sprawdzimy różnice.
Wizualizacja środowiska po instalacji DAS.
Budowa akwarium. Klaster GlassFish
Po zainstalowaniu DAS czas stworzyć przykładowy klaster. Wpierw stworzymy konfigurację naszego klastra na DAS’ie, do której będziemy podczepiać nowe instancje. Nowo dodane instancje synchronizują się z centralnym repozytorium DAS’a kopiując do repozytorium lokalnego aplikację którą będą hostować - instancje w klastrze są homogeniczne. Do stworzenia klastra wystarczy jedna prosta komenda:
asadmin create-cluster clusterA Po chwili otrzymamy odpowiedź.
Command executed successfuly
Po wykonaniu tej komendy w katalogu /kat_inst_glassfish/domain/domain1/config utworzył się katalog clusterA-config w wewnątrz którego w katalogu lib możemy dodać biblioteki tylko na potrzeby naszych instancji w klastrze. Utworzyliśmy klaster o nazwie clusterA. Oprócz utworzenia powyższych katalogów został zaktualizowany plik domain.xml opisujący naszą domenę domain1 o wpis na temat klastra. Po utworzeniu konfiguracji klastra czas dodać do niego instancje.
Wizualizacja środowiska po stworzeniu klastra.
Wizualizacja środowiska po stworzeniu klastra.
Budowa akwarium ciąg dalszy. Instalacja agentów
Naszą architekturę zbudujemy z czterech instancjach. Każda z nich będzie zainstalowana na oddzielnej wirtualce: zone02, zone03, zone04, zone05. Instalacja jest podobna jak w przypadku DAS.
Po dokonaniu tych czynności na każdej z wirtualek, sprawdzimy czy DAS ma komunikację za wszystkimi agentami. Logując się na Admin Console (https://zone01.host:4848/) w drzewie Node Agents zobaczymy listę naszych agentów w domenie:
Podgląd stanu agentów z poziomu Admin Console.
Wizualizacja środowiska po utworzeniu agentów.
Budowa akwarium ciąg dalszy. Instancje w klastrze
Obecnie utworzyliśmy nasz klaster clusterA dodając do niego cztery hosty. Czas utworzyć na hostach instancje GlassFish’a, które będą brać udział w mechanizmie HADB. W tym celu na każdej z wirtualek: zone02, zone03, zone04, zone05 zainstalujemy instancje już bezpośrednio z DAS. Mamy taką możliwość ponieważ uruchomiliśmy już agentów.
Stan klastra po utworzeniu instancji.
Aby uruchomić klaster wystarczy nam prosta komenda start-cluster w asadmin na DAS.
Po uruchomieniu tej komendy w drzewie Clusters –> clusterA zobaczymy nasze 4 aktywne instancje wraz z ich stanem.
Stan klastra po jego uruchomieniu
Stan środowiska po uruchomieniu klastra
Topologie HADB
Mechanizm rozproszonej bazy wysokiej dostępności pozwala na stworzenie dwóch topologii:
- Colocated (wraz z instancjami klastra)
- Separate tier (na oddzielnych nodach)
Pierwsza bazuje na użyciu tych nod’ów, na których pracują instancje w celu przechowywania replikacji sesji. Druga przewiduje użycie w tym celu odrębnych maszyn. Zwiększa to oczywiście wydajność instancji, ale nakłada wymogi na przepustowość sieci, oraz wymaga dodatkowego sprzętu.Z uwagi na prostotę naszego środowiska będziemy trzymać się pierwszej topologii – colocated.
Obie topologie przedstawione są na poniższych ilustracjach.
Topologia coolocated w HADB
Topologia separate tier w HADB
Teoria w HADB
Dwie przedstawione topologie charakteryzuje identyczna logiką działania HADB. Warto wpierw omówić kilka pojęć związanych z HADB, aby w pełni zrozumieć obie topologie. Omówimy:
- Domena HADB
- DRU
- Management Agent
- Active node
- Spare node
- Domena HADB - w obu topologiach mechanizm HADB tworzy odrębną domenę. Nie jest to domena w rozumieniu tradycyjnych domen GlassFish’a, ale domena skupiająca w sobie nod’y odpowiadające za repozytorium i replikacje sesji. Domena HADB skupia w sobie pary nod’ów, każda para replikuje sesje między sobą (A w B i B w A) w grupach zwanych DRU.
- DRU (Data Redundancy Unit) – są zawsze dwie. Każda z nich zawiera 100% replikację sesji. Nod wchodzący w skład jednego DRU ma w drugim DRU swego mirror’a, drugiego nod’a z którym replikuje sesje. Oba nod’y tworzą poziom. Do każdej domeny nod’y dodaje się lub usuwa parami, co skutkuje usunięciem bądź dodaniem nod’ów z obydwu DRU. Każdy DRU zawiera w sobie aktywne (active) oraz wolne (spare) nod’y.
- Management Agent – proces JVM, agenta HADB hostujący sesje na klasterze GlassFish. Może być active lub spare.
- Active node – nod aktywny wchodzący w skład DRU. Jest to działający proces Management Agent (MA), który bierze aktywny udział w domenie (hostuje oraz replikuje sesje).
- Spare node – jest to nod "zapasowy". Spare node jest podpięty pod dane DRU i pełni rolę backup’u. Jeśli z jakiś powodów proces MA przestaje działać w jego miejsce wchodzi Spare Node, który synchronizuje się pobierając replikacje sesji z mirror’a zakończonego procesu MA. W architekturze HADB Spare Nod’y są opcjonalne. Jeśli ich nie wykorzystamy to w przypadku awarii danego MA jego mirror hostuje swoje sesje plus replikacje sesji mirrora, co sprawia, że musi mieć zapasową moc obliczeniową.
Cała baza działa dopóki dopóty na każdym z poziomów działa przynajmniej jeden nod.
Poniżej przedstawiona jest przykładowa prezentacja architektury HADB z użyciem 4 nodów, 2 active, 2 spare.
Dodatkowo dołączony jest diagram struktur połączonych reprezentujący architekturę, którą będziemy budować.
Przykładowa architektura prostego HADB w topologii separate tier. W celu przejrzystości pominięto reprezentację klastra clusterA.
Diagram struktur połączonych zależności między domena a HADB
Budowa HADB. Uruchamianie agentów HADB
Pierwszą czynnością, którą przeprowadzamy podczas tworzenia HADB jest instalacja modułów HADB do każdej z instancji. Tą czynność już przeprowadziliśmy instalując moduły wraz z instancjami na samym początku.
Drugim krokiem jest uruchomienie agentów HADB. Agent HADB nosi nazwę Management Agent i odpowiada za obsługę tej części bazy, za którą odpowiada dany nod z bazie HADB. Dla przypomnienia dodam, że baza jest rozproszona, co za tym idzie jej schema jest podzielona względem ilości nod’ów, a każdy z nod’ów pracuje jedynie na swojej części bazy.
W celu uruchomienia Management Agent’a w katalogu instalacji GlassFisha mamy podkatalog hadb. To właśnie w nim znajdują się moduły do HADB, które w tej dystrybucji są dostępne w dwóch wersjach 4 oraz 4.4.3-21 jak widać po nazwach katalogów w katalogu hadb. Do naszych ćwiczeń użyjemy modułów 4.4.3-21. Uruchamiamy więc agenta (na każdej z wirtualek: zone02, zone03, zone04, zone05).
zone02 # cd /kat_inst_glassfish/hadb/4.3.3-21/bin/
zone02 # ./ma ma.cfg
Plik ma.cfg jest to plik konfiguracyjny agenta.
Poprawnym wynikiem uruchomienia agenta jest komunikat:
2010-02-14 18:04:27.203 INFO Listening for client connections on port 1862
Powyższy wydruk na konsole jest podsumowaniem po uruchomieniu agenta. Jak widać zgodnie z konfiguracją w pliku ma.cfg agent nasłuchuje na porcie JMX 1862, repozytorium przetrzymuje w podkatalogu /rep, logi agenta są zapisywane do pliku ma.log, a historia operacji na bazie jest przechowywana w podkatalogu /history.
Oprócz skryptu ma, który uruchamia nam agenta w katalog /bin znajdziemy:
clusql
hadbm
ma
ma-initd
ma.cfg
- clustersql – SQL Utility, narzędzie SQL do ręcznej pracy na bazie.
- hadbm – (High Avaliability Database Manager) narzędzie do zarządzania bazą HADB.
- ma – Management Agent, skrypt do uruchomienia agenta.
- ma-initd – skrypt do zarejestrowania agenta jako usługi w Solarisie do wersji 9 (od wersji 10 rejestrujemy do sami jako usługę w SMF).
- ma.cfg – plik konfiguracyjna agenta.
Po uruchomieniu agentów HADB, czas na budowę bazy.
Budowa HADB. Tworzenie bazy
Do stworzenia bazy w przypadku topologii colocated wystarczy nam jedna prosta komenda (w przełączniku hosts nie ma spacji między kolejnymi maszynami oraz nazwy maszyn podajemy używając FQDN - pełnych nazw domen):
zone01 # ./asadmin configure-ha-cluster --hosts zone02.example.com,zone03.example.com,zone04.example.com,zone05.example.com clusterA
Po dłuższej chwili (w zależności od sprzętu na jakim pracujemy 5 minut lub więcej) otrzymamy odpowiedź:
Command configure-ha-cluster executed successfully.
I w ten oto prosty sposób utworzyliśmy krok po kroku architekturę HADB.To co dzieje się przez tą komendę to uruchomienie w tle narzędzia hadbm i kolejno utworzenie domeny HADB, stworzenie schema dla bazy i dodanie nod’ów do DRU, wszystkich jako aktywne. Dzięki tej komendzie mamy najszybszy i najprostszy sposób to tworzenia HADB jednak tylko w topologii colocated. W przypadku topologii z użyciem oddzielnych maszyn musielibyśmy używać narzędzia hadbm i ręcznie krop po kroku tworzyli całą strukturę.
Uwaga: Dzięki narzędziu hadbm możemy zarządzać całą domeną HADB. Dodawać nod’y, zmieniać rozmiar używanej przestrzenie na dysku przez nod’y, czyścić bazę, refragmentować w przypadku dodania czy usunięcia nod’ów z DRU etc. Aby korzystać z tego mechanizmu wystarczy wdrożyć aplikację, domyślnie DAS korzysta z HADB. Dzięki HADB będziemy mieli zapewnioną dostępność i replikację komponentów SFSB.
Konfigurację HADB przeprowadzamy z poziomu Admin Console.
Konfiguracja Apache HTTPD do LoadBalancingu
GlassFish Configurator (glassfish-lbconfigurator-3_1.jar) automatycznie wykonuje niezbędne konfiguracje dla serwera HTTP Apache. Plug-In Loadbalancer wspiera Serwer HTTP Apache > 2.2.x.
Należy skompilować serwer HTTP Apache z obsługą SSL oraz modułem mod_jk, jeśli planujesz używać automatycznego równoważenia obciążenia zastosuj SSL. Konfiguracja musi być wykonana na serwerze przed instalacją Plug-ina. Można zastosować funkcję umożliwiającą zmiany dokonane w konfiguracji dzięki konsoli administracyjnej serwera GlassFish lub z linii poleceń: apply-http-LB-changes komenda być automatycznie przesyłana przez sieć do serwera www.
W wersji Open Source musimy jeszcze pobrać i uruchomić konfigurator Loadbalancera. W tym celu pobieramy i uruchamiamy go następująco: java -jar glassfish-lbconfigurator-3_1.jar.
Należy sprawdzić czy użytkownik „apache” ma dostęp (odczyt) do poniższych plików
apache-install-location/conf/loadbalancer.xml
apache-install-location/conf/sun-loadbalancer_1_2.dtd
JMS (Java Messaging Service)
Klienci (fragmenty systemu, aplikacje itp.) w środowisku rozproszonym mogą współdziałać poprzez wymianę komunikatów, przy czym:
- klient-producent wysyła komunikat
- klient-konsument odczytuje komunikat
- obaj klienci nie muszą działać równocześnie
- żaden z nich nie musi nic "wiedzieć" o budowie, kodzie itp. drugiego
Współdziałanie aplikacji poprzez wymianę komunikatów ma tę zaletę, że uniezależnia kody programów od siebie ("loose coupling")
Ten sposób programowania realizowany jest na różnych platformach poprzez różne technologie - np. IBM MQseries.
W środowisku Javy mamy do dyspozycji JMS (Java Messaging Service).
Java Messaging Service to API (zestaw interfejsów), które zapewnia m.in.:
- synchroniczną wymianę komunikatów (klient czeka na komunikat, spodziewa się go),
- asynchroniczną wymianę komunikatów (JMS wysyła komunikat do klienta, gdy tylko komunikat się pojawi, a klient nie musi sprawdzać czy komunikat jest, obsługuje go na zasadzie "callback"),
- niezawodność - gwarancję, że komunikat zostanie "dostarczony" raz i tylko raz.
Architektura JMS
Składowe aplikacji JMS
- serwis (JMS provider) implementuje interfejsy i dostarcza narzędzi administrowania
- klienci - tworzą, wysyłają i odbierają komunikaty
- obiekty administrowane - destynacje oraz fabryki połączeń (są zwykle tworzone i konfigurowane przez narzędzia administracyjne, ale również istnieje programistyczne API do tych celów)
Destynacja JMS jest miejscem w którym nadawca umieszcza wiadomości i z którego odbiorca odczytuje wiadomości.
Dwie możliwe domeny (rodzaje destynacji):
kolejka (Queue) - Point-to-Point za pośrednictwem kolejki komunikatów, nadawca wysyła do określonej nazwanej kolejki (destynacji), odbiorca - odbiera komunikat z tej kolejki.
- każdy komunikat może być odebrany tylko przez jednego odbiorcę;
- odbiorca może odebrać wiadomość niezależnie od tego czy nadawca działa czy też juz zakończył działanie;
- zasadą jest, że odbiorca potwierdza odebranie wiadomości, co zapewnia, że nie będzie mu ona przysłana po raz kolejny.
Temat (Topic) - zasada publikacji i subskrypcji.
- każda wiadomość może mieć wielu odbiorców (subskrybentów tematu),
- w danym temacie może publikował wielu nadawców,
- odbiorca może odbieracz tylko te wiadomości z danego tematu, które zostały opublikowane po zapisaniu się przez niego do subskrypcji
Uwaga: wersja 1.1 JMS pozwala na oprogramowanie obu typów komunikacji za pomocą tych samych interfejsów.
Architektura aplikacji JMS
ConnectionFactory - tworzy połączenie do dostawcy serwisu JMS.
Destination - określa destynację nadawanych i odbieranych wiadomości.
Konfigurowanie GlassFisha do obsługi JMS
Zanim rozpoczniemy pisanie kodu do obsługiz JMS API, musimy skonfigurować niektóre GlassFisha. W szczególności, należy skonfigurować fabryki połączeń (Connection Factories) oraz kolejki wiadomości.
Utworzenie fabryki połączeń JMS
Najprostszym sposobem na utworzenie fabryki połączeń JMS jest użycie konsoli internetowej w GlassFish. Konsoli internetowej możemy używac pod warunkiem, że najpierw wystartujemy nasz serwer
asadmin start-domain domena1
Następnie w przeglądarce logujemy się do panelu admina.
Fabryki połączeń można dodać rozwijając węzeł zasobów w drzewie w lewej stronie konsoli internetowej, rozwijając węzeł JMS Zasoby i klikając na węźle fabryk połączeń, a następnie klikając na przycisk New ... w głównym obszarze konsoli internetowej.
<br\>
Dla naszych celów, możemy większość danych zostawić domyślnych.Jedyną rzeczą, którą musisz zrobić, to wprowadzić Pool Name i wybrać Resource Type dla naszej fabryki połączeń.
Jest to zawsze dobry pomysł, aby użyć Pool Name zaczynającej się od "/". W ten sposób zasoby JMS można łatwo zidentyfikować podczas przeglądania drzewa JNDI.
W polu tekstowym Nazwa oznaczonego Pool wprowadź jms /GlassFishBookConnectionFactory. Nasz przykład kodu będzie używał tej nazwy JNDI w celu uzyskania odwołania do tej fabryki połączeń.
Typ zasobu menu rozwijane ma trzy możliwości:
- javax.jms.TopicConnectionFactory - wykorzystywane do tworzenia fabryki połączeń JMS, które tworzy tematy dla klientów JMS pomocą pub / sub domeny messaging
- javax.jms.QueueConnectionFactory - wykorzystywane do tworzenia fabryki połączeń kolejki JMS, które tworzy dla klientów JMS za pomocą wiadomości domenę PTP
- javax.jms.ConnectionFactory - wykorzystywane do tworzenia fabryki połączeń JMS, który tworzy zarówno tematy lub kolejek JMS
W naszym przykładzie wybierzemy javax.jms.ConnectionFactory. W ten sposób możemy korzystać z tej samej fabryki połączeń do wszystkich naszych przykładach i tych za pomocą wiadomości PTP i korzystających z pub / sub messaging domain.
Po wprowadzeniu Pool Name dla naszej fabryki połączeń, wybierając typ fabryki połączeń i ewentualnie wpisując opis naszej fabryce, musimy kliknąć na przycisk OK, aby zmiany odniosły skutek.
Konfiguracja kolejki JMS
Kolejki JMS mogą być dodawane przez rozwinięcie węzłów zasobów (Resources ) w drzewie w lewej stronie konsoli internetowej, rozwijając węzeł JMS Resources i klikając na węźle Resources Destination, a następnie klikając na przycisk New w głównym obszarze konsoli internetowej.
W naszym przykładzie, nazwa JNDI kolejki to jms/GlassFishBookQueue.Typ zasobu do kolejki komunikatów musi być javax.jms.Queue. Dodatkowo, Physical Destination Name musi być wprowadzony. W tym przykładzie jest to GlassFishBookQueue jako wartość tego pola.
Po kliknięciu na button Nowy , wpisując odpowiednie informacje dla naszej kolejki, a następnie klikając na przycisk OK, powinniśmy zobaczyć nowo utworzoną kolejkę.
Ustawianie tematu wiadomości (JMS message topic)
Konfiguracja wiadomości JMS w GlassFish jest bardzo podobne do konfigurowania kolejki JMS.
W konsoli internetowej, GlassFish, rozwiń węzeł Zasoby w drzewie po lewej stronie, a następnie rozwiń węzeł JMS Resouces i kliknij na węźle Destination Resources node, a następnie kliknij przycisk Nowy w głównym obszarze konsoli internetowej.
Nasze przykłady wykorzystują nazwę JNDI jms/GlassFishBookTopic, ponieważ jest to temat wiadomości, pole Resource Type musi być ustawione javax.jms.Topic. Pole Opis jest opcjonalny. Pole Physical Destination Name jest wymagane, w naszym przykładzie użyjemy GlassFishBookTopic jako wartości dla tej właściwości.
Po kliknięciu na przycisk OK, możemy zobaczyć nasz nowo utworzony temat wiadomości:
Teraz, gdy mamy utworzone fabryki połączeń :) kolejki wiadomości oraz wiadomości, możemy rozpocząć pisanie kodu za pomocą JMS API.
Loadbalancing - HAProxy
Opis
Wyobraźmy sobie sytuację, że mamy serwis z dość dużą oglądalnością, wszelkie optymalizacje już zawodzą, programiści przepisali 50% zapytań SQL, administratorzy baz danych wrzucili 75% jej zawartości do pamięci RAM, memcache robi się czerwony od ilości GET’ów a serwis i tak działa coraz wolniej… rozkładamy ręce i szukamy rozwiązania do balansowania ruchu na kilka serwerów.
Haproxy – jak możemy wyczytać z dokumentacji, jest to reverse proxy TCP/HTTP dla środowisk wysokiej dostępności, potrafiące m.in:
- route’ować pakiety HTTP na podstawie zawartych Cookie
- przełączać ruch na inny serwer w przypadku wykrycia awarii
- blokować requesty HTTP na podstawie analizy nagłówków
- generować statystyki ruchu/usług
- modyfikować nagłówki HTTP w locie (coś dodać, coś usunąć, coś zmodyfikować)
- zatrzymać przyjmowanie nowych połączeń bez zrywania nawiązanych
- i wiele wiele więcej
Opiszę prosty przykład konfiguracji haproxy, który będzie można użyć do balansowania ruchu HTTP do dwóch serwerów.
Schemat konfiguracji Hostów dla HAProxy
- xen2 – serwer z HTTP Apache – 192.168.1.241
- xen3 – serwer z HTTP Lighttpd – 192.168.1.242
- xen4 – serwer z HTTP Nginx – 192.168.1.124
- xen7 – serwer z haproxy – 192.168.1.220
Nie chcę opisywać sposobu instalacji haproxy, bo każdy wybierze swoją drogę, apt-get install haproxy, emerge haproxy, wget haproxy-1.3.17.tar.gz; ./configure; make; make install, itd… mając zainstalowane haproxy, możemy zacząć konfigurację:
- vi /etc/haproxy.cfg
- global – ustawienia typu logowania, ilości maksymalnej połączeń, uid’a, gid’a, itd…
- default – ustawienia domyślne dla wszystkich usług frontend/backed.
- listen – sekcja właściwa która nas będzie interesowała w tym momencie
Nasza przykładowa konfiguracja wygląda następująco:
root@xen7:~# cat /etc/haproxy.cfg global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 user haproxy group haproxy defaults log global mode http option httplog option dontlognull retries 3 redispatch maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000 option httpclose listen xen 192.168.1.220:80 balance roundrobin server xen2 192.168.1.241:80 server xen3 192.168.1.242:80 server xen4 192.168.1.125:80
Czyli mamy sekcję listen (nazwa usługi xen) słuchająca na adresie IP load-balancer’a, na potrzeby tego opisu tak może być, ale najlepiej jest każdą usługę (klaster) bindować do innego adresu IP, balance roundrobin oznacza, że requesty będą rozdzielane kolejno do każdego node’a xen2, xen3, xen4 i niżej jest już sama definicja node’ów, server xen2, 3, 4, oraz IP do których należy przekierować requesty.
Uruchamiany daemona (dla testów w trybie foreground i debug):
root@xen7:~# haproxy -dV -f /etc/haproxy.cfg Available polling systems : select : pref=150, test result OK sepoll : disabled, test result OK epoll : disabled, test result OK poll : disabled, test result OK Total: 4 (1 usable), will use select. Using select() as the polling mechanism.
W praktyce 3 requesty wyglądają tak:
sampler:~ jamzed$ lwp-request -Sde xen7|grep Server Server: lighttpd/1.4.19
sampler:~ jamzed$ lwp-request -Sde xen7|grep Server Server: nginx/0.5.33 sampler:~ jamzed$ lwp-request -Sde xen7|grep Server Server: Apache/2.2.8 (Ubuntu)
W konsoli widzimy debug:
00000002:xen.accept(0003)=0005 from [192.168.1.182:54865] 00000002:xen.clireq[0005:ffff]: GET / HTTP/1.1 00000002:xen.clihdr[0005:ffff]: TE: deflate,gzip;q=0.3 00000002:xen.clihdr[0005:ffff]: Connection: TE, close 00000002:xen.clihdr[0005:ffff]: Host: xen7 00000002:xen.clihdr[0005:ffff]: User-Agent: lwp-request/5.810 00000002:xen.srvrep[0005:0006]: HTTP/1.1 200 OK 00000002:xen.srvhdr[0005:0006]: Server: nginx/0.5.33 00000002:xen.srvhdr[0005:0006]: Date: Fri, 19 Jun 2009 17:32:57 GMT 00000002:xen.srvhdr[0005:0006]: Content-Type: text/html 00000002:xen.srvhdr[0005:0006]: Content-Length: 151 00000002:xen.srvhdr[0005:0006]: Last-Modified: Wed, 30 Aug 2006 10:39:17 GMT 00000002:xen.srvhdr[0005:0006]: Connection: close 00000002:xen.srvhdr[0005:0006]: Accept-Ranges: bytes
przychodzący request (GET / HTTP/1.1) – nagłówki od klienta xen.clihdr i pełną odpowiedź serwera xen.srvhdr.
Takim sposobem udało nam się szybko zrobić w prosty sposób load-balancer HTTP, jest to tylko ułamek tego co potrafi haproxy.
A jakie są Wasze preferencje co do balanserów? LVS? A może jakieś sprzętowe?
Kierowanie ruchu HTTP na podstawie żądanego contentu/typu danych
<br\><br\><br\><br\> Mamy jeden serwis w jednej domenie http://yoursite.pl/ i posiadamy tylko jeden adres IP, ale chcemy podawać content w zależności od żądanego pliku z różnych serwerów, apache sprawdzi się przy (.php .html), lighttpd lekki, szybki, zwinny, etc. doskonale poradzi sobie z obrazkami (.gif .jpg), a nginx’a chcemy użyć bo też jest modny, do podawania (.js .css), <br\>bez balancera w postaci haproxy który pracuje w 7 warstwie i potrafi analizować i wykonywać przeróżne akcje niczym ninja z filmów z dzieciństwa na nagłówkach HTTP byłoby to trochę bardziej skomplikowane. <br\>Zakładam, że mamy działające haproxy i pozostałe serwery httpd, jeśli tak to można troszkę pobawić się konfiguracją.<br\> Zacznę od wyjaśnienia kilku pojęć:<br\>
- frontend – zgodnie z dokumentacją, frontendem jest nasza usługa która przyjmuje połączenia od użytkowników i je proxy’uje dalej do backendów.<br\>
- backend – to definicja serwerów które odbierają ruch od balancer’a i zwracają wyniki, w naszym przypadku backendami są serwery Apache, Lighttpd, Nginx.<br\>
- acl – Access List, dzięki acl’kom możemy zmatchować dany request np. na podstawie src, dst, path_reg, path_end<br\>
Nasza konfiguracja haproxy będzie wyglądać następująco:<br\>
root@xen7:~# cat /etc/haproxy.cfg global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 user haproxy group haproxy> defaults log global mode http option httplog option dontlognull retries 3 maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000 option httpclose frontend frontend_xen bind 192.168.1.220:80 option forwardfor acl acl_apache path_end .jsp .html acl acl_lighttpd path_end .gif .jpg acl acl_nginx path_end .css .js use_backend backend_xen2 if acl_apache use_backend backend_xen3 if acl_lighttpd use_backend backend_xen4 if acl_nginx default_backend backend_xen2 backend backend_xen2 mode http balance roundrobin server xen2 192.168.1.241:80 check backend backend_xen3 mode http balance roundrobin server xen3 192.168.1.242:80 check backend backend_xen4 mode http balance roundrobin server xen4 192.168.1.125:80 check
Po starcie daemona przeprowadzamy mały test:
$ lwp-request -Sde http://xen7/test.jsp | grep Server Server: Apache/2.2.8 (Ubuntu) $ lwp-request -Sde http://xen7/test.css | grep Server Server: nginx/0.5.33 $ lwp-request -Sde http://xen7/test. jpg | grep Server Server: lighttpd/1.4.19<br\><br\>
Kluczową rolę odegrały definicje frontendu oraz backendów, ale bez ACL nie moglibyśmy powiedzieć balancer’owi jaki ruch gdzie kierować. Definiujemy więc 3 ACLe (acl_apache, acl_lighttpd, acl_nginx) gdzie warunkiem jest rozszerzenie:<br\><br\>
acl acl_apache path_end .jsp .html acl acl_lighttpd path_end .gif .jpg acl acl_nginx path_end .css .js
składnia:<br\> acl nazwa_acla sposób_matchowania warunek<br\> Kolejny bardzo ważny element konfiguracji to wskazanie balancerowi gdzie ma kierować ruch po dopasowaniu do konkretnej acl’ki:<br\>
use_backend backend_xen2 if acl_apache use_backend backend_xen3 if acl_lighttpd use_backend backend_xen4 if acl_nginx default_backend backend_xen2
Jeśli request pasuje do ACL acl_apache to kieruj do backend_xen2, jeśli pasuje do acl_lighttpd to kieruj do backend_xen3, itd… jeśli nie dopasuje do żadnej acl kieruje do default’owego backendu backend_xen2. Bardzo proste do wdrożenia i daje nam ogromne możliwości zarządzania streamem HTTP, operowanie na rozszerzeniach to ułamek możliwości tego load balancer’a, będę starał się co jakiś czas, opisywać inne/pozostałe ciekawe przykłady wykorzystania haproxy.<br\><br\>