Linux + Glassfish 4.0 High availability Load Balancing Cluster – osa 1

Sain taannoin loistavan syyn perehtyä toimintavarman ja skaalautuvan järjestelmän rakentamiseen Glassfish serverin vinkkelistä – olen aiemmin rakentanut vastaavia mm. JBOSS alustalla. Tässä mitä teen ei ole mitään mullistavaa, nykyisellään löytyy paljon teknisesti jännempiäkin juttuja mm. Riak, MongoDB, Hadoop, ja pilvipalveluiden ajatusmaailmasta. Mutta tämä on yksi kätevä työkalu pakissa: miten saada Java sovelluspalvelin toimimaan katkotta yli käyttöhäiriöiden ja päivitysten, ja miten saada se skaalautumaan yli satojen yhtäaikaisten käyttäjien (satoja saa yhdelläkin serverillä vaikka mitenpäin aikaiseksi).

Perusidea on vähintäänkin tuplata kaikki: Jotta saadaan serveri vikasietoiseksi, niitä tulisi olla ainakin se kaksi (mieluiten enemmän), ja jos jotain tilaa on käytetty, se pitäisi jotenkin replikoitua. Mutta vikasietoisuus on yhtä vahva kuin heikoin lenkki: glassfish serverien replikointi ei vielä riitä. Siihen tarvitaan eteen mylly joka reitittää pyynnöt toimiville serverille, load balancer toisinsanoen. Mutta mitä jos load balancer kaatuu? No niitäkin tarvitaan kaksi, tai enemmän, siten että yhden ollessa maissa toinen ottaa sen paikan. Entäpä.. taustatietokannat? Verkko? On paljon kahdennettavia kohtia.

Tämän voi tehdä monella tapaa, mutta itseä viehätti tällainen malli: Joka serveri on virtuaalikone, jossa on Glassfish serveri, Apache Http serveri Load balancerina, ja MySQL tietokanta. Periaatteessa siis joka mylly on lähes identtinen, ja sisältää kaiken tarvittavan. Skaalautuvuutta ja vikasietoisuutta saadaan siis lisäämällä myllyjä – ainakin tiettyyn rajaan asti (Session replikointi, sen tarve ja ratkaisuperiaate vaikuttaa skaalautuvuuden skaalautuvuuteen – ja kaikki serveriresurssit eivät muutenkaan skaalaudu niin hyvin 😉

Tuossa on kuva siitä miltä tämmöinen voisi näyttää – ei ole oma mutta kuvaa niin hyvin mistä on kyse että menköön (lopussa on lähdeviittaus sivustoon josta kuva ja alkuperäiset ideat ovat peräisin):

diagram

No niin, olen jo aiemmin käsitellyt aihetta, miten asennetaan Debian alustalle yksi Glassfish instanssi – joten se tarvitaan tietysti pohjaksi. Samalla kaavalla tehdään vähintään kaksi lähes identtistä serveriä – jotka näkevät toisensa (ping toimii ristiin).

Ensimmäinen askel on poistaa paikallinen serveri ja http kuuntelijat – koska niiden tilalle tulee klusterin instanssikuuntelijat. Tämä tehdään molemmille myllyille, ja Glassfish täytyy olla käynnissä aluksi:

#run these on both debian1 and debian2 machines

$ asadmin delete-http-listener http-listener-1

$ asadmin delete-http-listener http-listener-2

$ asadmin delete-virtual-server server

Selvä pyy. Vaihdetaan seuraavaksi Glassfish tunnukseen, koska sillä serverit ajavat käskyjään, ja luodaan ssh avainparit joilla serverit voivat viestiä. Tämän voit ajaa vain node1 koneesta – ellet sitten halua Domain Admin nodea molempiin koneisiin. Huomaa että glassfish tunnuksella tulisi tässä kohtaa olla myös salasana – sama molemmissa nodeissa. Ellet ole sellaista luonut, aja passwd glassfish nyt.

Tässä esimerkissä koneiden verkkonimet ovat: debian1.mycompany.com ja debian2.mycompany.com:

#run this only on debian1 machine

sudo su --shell /bin/bash glassfish

asadmin setup-ssh --generatekey=true debian1.mycompany.com

# seuraava komento antaa virheen koska glassfish on jo asennettu kakkosnodeen, mutta 
# se myös mukavasti tarkistaa että kommunikaatio pelaa

asadmin install-node debian2.mycompany.com

Seuraava askel, luodaan kaksi hallinta-nodea Glassfishiin:

# run this on debian1 machine

asadmin create-node-ssh --nodehost localhost debian1-ssh 

asadmin create-node-ssh --nodehost debian2.mycompany.com debian2-ssh

Nämä ovat ssh nodeja, eli näiden avulla Glassfish voi yhdestä DA-serveristä käsin lähettää ssh-protokollalla komentoja kaikille klusterin nodeille.

Seuraavaksi luodaan klusteri ja kaksi serveri-instanssia siihen:

# run this on debian1 machine

asadmin create-cluster --systemproperties HTTP_SSL_LISTENER_PORT=8181:HTTP_LISTENER_PORT=8080 cluster1 

asadmin create-instance --cluster cluster1 --node debian1-ssh debian1-gf

asadmin create-instance --cluster cluster1 --node debian2-ssh debian2-gf

Jos tähän asti kaikki sujui, seuraavaksi tehdään Load Balanceriä varten AJP-palvelut. Tässä kikkaillaan vähän – ja asetetaan järjestelmämuuttujiin (system properties) instanssin nimi jota voi serverissä sitten käyttää esim. virtuaalikoneparametreissa kätevästi:

# run this on debian1 machine

asadmin create-http-listener --listenerport 8009 --listeneraddress 0.0.0.0 --defaultvs server --target cluster1 jk-connector

asadmin set configs.config.cluster1-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

asadmin create-jvm-options --target cluster1 "-DjvmRoute=\${AJP_INSTANCE_NAME}"

asadmin create-system-properties --target debian1-gf AJP_INSTANCE_NAME=debian1

asadmin create-system-properties --target debian2-gf AJP_INSTANCE_NAME=debian2

Seuraavaksi, piipahdetaan molemmilla koneilla vaihtamassa masterpassword – mutta siten että se tallettuu tiedostoon jolloin sitä ei koko aikaa kysellä:

# run this on debian1 machine

asadmin change-master-password --savemasterpassword true debian1-ssh

#run this on debian2 machine:

asadmin change-master-password --savemasterpassword true debian2-ssh

Ja lopulta, talletetaan myös tavallinen admin salasana tiedostoon, jotta asadmin työkalun ajo ei juutu dialogeihin:

# on debian1:

asadmin --host debian2 --port 4848 login 

#on debian2:

asadmin --host debian1 --port 4848 login

Nyt ollaan jo aika loppusuoralla. Meillä on jo ennestään init scripti joka ajaa glassfish domain serverin (ja tässä tapauksessa DAS) käyntiin, mutta kannattaa ehkä lisätä scripti joka käynnistää myös molemmissa koneissa instanssin – tai clusterin. Editoi tiedostoa etc/init.d/glassfish-inst ja pistä sinne jotain tämäntapaista:

#!/bin/sh
#
# glassfish init script for Linux 
# It only starts one instance by name. The instance needs to have
# .asadminpass and .asadmintruststore password files created
# for the user.
#
# .asadminpass is created via "asadmin login" command
# .asadmintruststore is created via 
# "asadmin change-master-password --savemasterpassword true"
### BEGIN INIT INFO
# Provides: glassfish-inst
# Required-Start: $local_fs $remote_fs $network $syslog $named
# Required-Stop: $local_fs $remote_fs $network $syslog $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Start/stop a glassfish instance
### END INIT INFO

GLASSFISH_HOME=/opt/glassfish4
GLASSFISH_USER=glassfish
GLASSFISH_INSTANCE=debian1-gf

case $1 in

start)
 echo "Starting Glassfish local instance ${GLASSFISH_INSTANCE}..."
 su - "${GLASSFISH_USER}" -c \
 "${GLASSFISH_HOME}/bin/asadmin start-local-instance "${GLASSFISH_INSTANCE}""
 ;;

stop)
 echo "Stopping Glassfish local instance ${GLASSFISH_INSTANCE}..."
 su - "${GLASSFISH_USER}" -c \
 "$GLASSFISH_HOME/bin/asadmin stop-local-instance "${GLASSFISH_INSTANCE}""
 ;;

restart)
 echo "Restarting Glassfish local instance ${GLASSFISH_INSTANCE}..."
 su - "${GLASSFISH_USER}" -c \
 "$GLASSFISH_HOME/bin/asadmin restart-local-instance "${GLASSFISH_INSTANCE}""
 ;;

*)
 echo "usage: $0 (start|stop|restart|help)"

esac

Huom! Vaihda ylläolevassa tuo GLASSFISH_INSTANCE arvoon 1, 2, tai mitä serveriä käsitteletkään. Joka serverillä se tulee tietysti olla omansa. Jos käynnistät clusterin, se tietysti potkaisee joka instanssin käyntiin kerralla. Tätä tapaa en kuitenkaan vielä ehtinyt kokeilemaan.

Seuraavaksi pistetään tämäkin automaattikäynnistymään:

sudo chmod 755 /etc/init.d/glassfish-inst

sudo update-rc.d glassfish-inst defaults

No niin, sitten vain boottia kehiin. Serverin 1 pitäisi toimia DAS-serverinä, joten sen kautta voit käydä ihan hallintakonsolista katsomassa miltä kaikki näyttää. Kannattaa myös kokeilla asentaa joku pieni ja varmasti toimiva klusterisovellus ja testata vähän miten se asentuu kaikille instansseille, ja miten se käyttäytyy kun instanssit sammuvat ja taas käynnistyvät.

Sellainen löytyy esim. täältä: http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/clusterjsp.war

Pari huomiota sessioreplikoinnin vaatimuksista ja nykytilasta:

Glassfish 4.0 ei virallisesti tue HA piirteitä, mutta siellä on olemassa early access joka toimii ihan hyvin. 4.1 versiossa olisi paremmin testattuna tulossa samat piirteet. Glassfish versioissahan on aina joissain klusterituki, joissain ei, eli kannattaa olla tarkkana version kanssa.

Glassfish 4.0 tukee eri replikointitavoista vain in-memory tapaa, joka tarkoittaa että nodet heittelevät verkon yli toisilleen notifikaatioita, ja replikoivat sessiodataa. Tämä ei ole parhaiten skaalautuva malli, mutta pienille ja keskikokoisille klustereille joissa sessiotilaa ei ole valtavasti ihan ok malli. Tämä edellyttää että klusterissa on GMS palvelu päällä, ja nodet näkevät toisensa verkossa. Hyvä myös tarkistaa että konfiguraation availability service alla on rastit oikeissa laatikoissa, mutta oletuksena pitäisi olla.

gms_service_enabled

availability_service_enabled

Mutta vielä on tärkeä huomioitava asia: Asennettava sovellus tulee olla availability-yhteensopiva ja availability-moodissa. Ensimmäinen edellyttää web.xml tiedostossa distributable=true arvoa (tai ei ollenkaan web.xml tiedostoa). Toinen vaatii että availability laitetaan päälle joko asennettaessa sovellus tai sen jälkeen. Esim. kun asensin em. clusterjsp sovelluksen oletusasetuksilla, siitä jäi rasti pois ruudusta, jolloin sessiot eivät replikoituneet.

availability_enabled

Voit myös kokeilla näkevätkö serverit toisensa ajamalla molemmissa nodeissa about yhtäaikaa tämän:

asadmin validate-multicast

 

Tässä tämä tällä kertaa. Tästä lähteestä ammensin paljon ideoita ja käytännön säätöjä:

http://blogs.nologin.es/rickyepoderi/index.php?/archives/53-Simple-but-Full-Glassfish-HA-Using-Debian.html

Jos tykkäät mielummin tehdä näitä UI:n puolella, tässä hyvä tutoriaali siihen (Glassfish 3 oppaat pätevät suurimmalta osin Glassfish 4:seen):

http://javadude.wordpress.com/2011/04/25/glassfish-3-1-clustering-tutorial/

 

Mainokset

Vastaa

Täytä tietosi alle tai klikkaa kuvaketta kirjautuaksesi sisään:

WordPress.com-logo

Olet kommentoimassa WordPress.com -tilin nimissä. Log Out / Muuta )

Twitter-kuva

Olet kommentoimassa Twitter -tilin nimissä. Log Out / Muuta )

Facebook-kuva

Olet kommentoimassa Facebook -tilin nimissä. Log Out / Muuta )

Google+ photo

Olet kommentoimassa Google+ -tilin nimissä. Log Out / Muuta )

Muodostetaan yhteyttä palveluun %s