Ngoprek Load Balancer di Glassfish Cluster….
Wah… susah memang bikin load balancer di glassfish yang dicluster ini… selain dokumentasinya gak begitu jelas… berhasilpun gak tahan sama serangan request yang banyak… weleh…
Di blog-nya sun bilang kalo pemakaian load balancer di glassfish bisa menggunakan plugin bawaan sun java application server (ini buat sun java web server), apache dengan plugin mod_jk, serta hardware load balancer yang support L7 (L7 ini maksudnya yang aware dengan layer ke 7 OSI, yaitu application layer. Biasanya load balancer handle di layer 4).
Mengikuti yang paling mudah dikerjakan, yaitu pake apache dan mod_jk. Di sini dijelaskan settingnya. Cara ini pake protokol ajp (standar tomcat). Jadi di glassfish tinggal ditambahkan -Dcom.sun.enterprise.web.connector.enableJK=8009 di JVM parameternya. OK, berhasil setting dan bisa jalan dengan aman. Oh ya, mod_jk ini ambil langsung binary-nya, gak pake compile, soalnya males
. Udah deh, di load test pake jmeter nembak ke load balancer-nya… dan hasilnya… oohhh kuat ternyata. Coba dipasang script aplikasi logger (ini aplikasi logger pake servlet) langsung di detik family….. weks.. gak kuat
. Jika diteliti pake netstat, keliatan kalo request ke port 8009 macet. Status koneksi SYN_RECV, tapi gak ditindak lanjuti. Udah deh, script buat nembak ke aplikasi logger di cabut dari detik family. Utak atik dari parameter kernel, apache, glassfish, mod_jk… tetap aja macet di port 8009. Wah ini kayaknya masalah di mod_jk konektor ke glassfish-nya. Di log glassfish gak kelihatan apa-apa. Jadi bingung… wahh… cari alternatif lainnya ahhh…
Oke deh, coba pake sun java web server… ambil yang versi 6. Direkomendasikan katanya. Oke.. tancap.. download…. lhaaa… kok supportnya cuman 32. Padahal server 64 bit.. weleh.. Cari-cari info… oh bisa ternyata.. harus install ia32-libs. Sesudah diinstall, ehhh gak taunya Web Server-nya gak jalan waktu install, harus install libstdc yang support dia lah, libtermcap yang gak ada di server (udah diganti dengan libncurses). Ribettt…. udah.. cari yang 64 bit. Cari link-nya di website…. ada… tapi versi terbaru (versi 7). Itupun yang disupport cuman buat distro Red Hat sama Suse doang…. ya udah dicoba dulu, mungkin bisa. Diinstall.. OK…. jalan… cari load balancernya sekarang. Ada linknya, tapi bentuknya binary. Wah ini bakalan sulit cari dependensi library-nya kalo bermasalah, soalnya ini pake distro ubuntu. Ublak-ublek sampai bosenn… dan ternyata gak mau jalan… sh*t…sh*t… Dicoba kombinasi binary load-balancer plugin berbagai macam versi. Tetap aja gak mau jalan di Sun Java Web Server. Kacauuu… cari alternatif lain lagi. Pas waktu lihat-lihat isi package load balancernya… wah.. rupanya juga menyediakan versi apache-nya. Horeee…. udah deh.. install lagi apache-nya…. load module-nya… dan blarrr…… error dimasalah dependency.. cari punya cari… ternyata module-nya cuman buat apache 2.0 aja… versi baru (2.2) gak bisa, karena ada perbedaan exported library buat cantolin ke apache. Udah deh, compile apache versi lama 2.0. Load module lagi di conf-nya… bisa jalan… kemudian coba jalanin request ke web load balancer…. SIGSEGV (segmentation fault) … gubrakkk…. WAAAHHHH… gak jalan lagi.. gak jalan lagi … susah musuh sama binary gak ada source-nya… Udah dibelain gak tidur semalaman… udah deh.. berhenti dulu… cari jalan lain…
Nyerah… nyerah. Akhirnya dicobalah jalanin salah satu aja koneksi ke web servernya glassfish, gak pake load balancer. Karena di cluster, tindak lanjut proses logger aplikasi ini bisa di balance sendiri di glassfish-nya (servlet lempar ke JMS, MDB ambil message, dan masukin ke DB. Proses lempar JMS udah di balance). Jadi benar-benar mengorbankan satu web server-nya untuk mendapatkan pukulan berat request-request. Karena abis diutak-atik konfigurasi glassfish-nya. Mulai dari Thread pool size, JDBC connection pool size, MDB pool size dan setting lain-nya yang udah agak lupa (sialan..lupa dokumentasi’in). Ternyata dicoba di detik family kuat.. satu hari aja bisa sampe 2 juta record. Yah, lumayan lah… gak pake balancer masih jalan. Tapi masih belum sreg… tuh load balancer kenapa yahh… Jadi pengin tau dalemannya.
Pertanyaan muncul, kenapa kok harus pake protokol AJP bawaan tomcat? Jawabannya adalah karena bisa sticky session. Jadi untuk aplikasi web yang memakai session, request yang diproses oleh salah satu server (glassfish) akan tetap memakai server tersebut untuk request-request berikutnya. Ini menghindari request dengan session yang sama dilempar pontang-panting ke server-server glassfish. Meskipun glassfish yang di cluster mampu handle replication. Ini untuk meminimalisir kinerja dari server glassfish itu sendiri. Sebenarnya ada fitur tambahan lain selain sticky session ini. Ada health checker, quiesce (upgrade aplikasi secara transparan ke user), monitoring, dan lainnya (lupaaa.. sini nih penjelasannya). Sebenarnya yang penting ini yang sticky session-nya.
Mekanisme sticky session kalo di java jelas dengan melihat session id yang ada di cookie (biasanya JSESSIONID namanya). Jadi jika ketahuan session id-nya, bisa tahu dilempar ke server mana yang sebelumnya handle session id tersebut. Nah, bertepatan dengan itu penulis juga coba cari alternatif lain dari load balancer ini. Sebenarnya bawaan native apache sudah ada module-nya. Yakni mod_proxy, yang di extend fungsionalitasnya untuk mendukung lebih dari sekedar http, tapi juga ftp dan protokol ajp. Lha terus kenapa gak coba pake bawaan apache tersebut. Ini sebenarnya yang rancu, karena googling kemarin menyarankan pake mod_jk, karena masih aktif maintaining-nya. Tapi setelah coba googling lagi, ada yang bilang suruh pake native module bawaan apache daripada mod_jk. Ini yang bener yang mana ???
Baca-baca lagi lebih dalam tentang mekanisme sticky session di module mod_proxy bawaan apache. Coba pakai yang versi http, sikat langsung ke port 38080 (web server glassfish), gak pake protokol AJP (soalnya kalo dipikir sama aja, masalah-nya ada di konektor AJP Glassfish-nya). Mod_proxy ternyata juga ada mekanisme sticky session-nya. Baca di sini untuk detil manual-nya. Setting di apache-nya:
1 2 3 4 5 6 7 8 9 10 11 12 | ProxyRequests Off <Proxy balancer://myCluster> BalancerMember http://kamplong:38080 route=kamplong BalancerMember http://ciplukan:38080 route=ciplukan </Proxy> ProxyPass /balancer-manager ! ProxyPass / balancer://myCluster/ stickysession=JSESSIONID ProxyPassReverse / balancer://myCluster/ <Location /balancer-manager> SetHandler balancer-manager </Location> |
Sebelumnya gak ada tambahan parameter route-nya. Setelah itu dicoba aplikasi servlet/jsp yang pake session. Kemudian dipantau menggunakan balancer-manager-nya. Request ke load balancer untuk memanggil jsp hello (bawaan sample glassfish). Hasilnya OK, aplikasi jalan untuk penggunaan session, pantau pake balancer-manager… lha.. kok requestnya di pontang-pantingkan dari kamplong ke ciplukan, kemudian ke kamplong lagi.. terus ke ciplukan… Ini pake session yang sama. Kayaknya ada yang kurang nih. Baca-baca lagi. Ada yang salah kayaknya. Jika log apache di set level debug, ketahuan kalo server apache gak menemukan route untuk session id yang sama dipanggil sebelumnya. Selidik punya selidik, lihat di source-nya apache (mod_proxy_balancer.c). Rupanya mod_proxy ini melakukan pengecekan isi JSESSIONID, yang dimana isinya gak sekedar karakter ascii (base-64 kah??. gak tau dah istilahnya), tapi ada tambahan “.” dengan tambahan string karakter. Perasaan kok JSESSIONID hampir sama dengan PHPSESSIONID, gak pake tambahan gituan. Apa ya? googling lagi… Ketemu forum yang membahas mod_proxy apache ini, rupanya acuannya juga sama, lihat di-source-nya rupanya ada pengecekan string karakter di variable JSESSIONID setelah karakter “.”. Rupanya ini menyangkut dengan mekanisme tomcat/glassfish sendiri. Ada istilah jvmroute yang ternyata dipakai untuk mekanisme load balancing sticky session. Jadi sebenarnya server tomcat/glassfish yang memproses request, akan menambahkan isi dari JSESSIONID dengan karakter “.” dan tambahan string variable jvmroute. Ini untuk penanda bagi load balancer, bahwa untuk request selanjutnya, untuk session yang sama, load balancer akan tahu dari cookie-nya request, bahwa request tersebut sebelumnya diproses di server yang memakai setting route = jvmroute. Jadi di server harus ditambahkan variable jvmroute dengan id tertentu yang unik untuk masing-masing server.
Jadi di masing-masing bagian system paramater di glassfish, penulis tambahkan variable INSTANCE_NAME dengan nama unik berbeda di masing-masing instance yang tercluster. Kalau di admin console masuk Configuration->cluster-config->system properties. Add property dengan nama INSTANCE_NAME. Dan click Instance values. Disini baru bisa di set untuk masing-masing server instance yang tercluster. Setelah itu tinggal set jvmroute di JVM settings->JVM options. Isi dengan -DjvmRoute=${INSTANCE_NAME}. Jadi dari situ kelihatan, nantinya untuk masing-masing instance, akan set jvmroute sesuai dengan nama INSTANCE_NAME-nya. Setelah itu masing-masing instance harus di restart.
Dicoba lagi. Pantau di balancer-manager. Horeee…. akhirnya sticky session-nya bisa…. Suksesss…….