Archive

Archive for the ‘Server’ Category

Ngoprek Load Balancer di Glassfish Cluster….

June 25th, 2008

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 :D . 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…….

admin Self QA, Server

Clustering di Glassfish v2

May 5th, 2008

Mengambil dari sini. Soalnya caranya lebih bisa dimengerti. Intinya bikin domain dulu (default domain1). Setelah itu baru bikin node agent yang konek ke domain tersebut. Dari situ tinggal buat instance di masing-masing node-agent. Sebelumnya domain1 harus terkonfigurasi jadi cluster. Berikut langkah-langkahnya; asumsinya punya 2 mesin yang dibuat cluster.

  1. Ekstrak glassfish.jar di masing-masing host. (misal host A dan B)
  2. Setup menggunakan konfigurasi cluster di dua2nya. (ant -f setup-cluster.xml)
  3. Apabila DAS di taruh di host A, maka jalankan domainnya (asadmin start-domain)
  4. Setelah itu baru buat node agent di masing-masing host yang mengarah ke domain yang kita buat ((host A)asadmin create-node-agent –host A agent-A. (host B)asadmin create-node-agent –host A agent-B)
  5. Jalankan node agent ((host A)asadmin start-node-agent agent-A. (host B)asadmin start-node-agent agent-B)
  6. Buat cluster di domain1. (asadmin create-cluster ABcluster)
  7. Bikin instance di masing-masing node-agent dibawah cluster ABcluster ((host A)asadmin create-instance –cluster ABcluster –nodeagents agent-A –host A instance-A. (host B) asadmin create-instance –cluster ABcluster –nodeagents agent-B –host A instance-B)
  8. Setelah selesai tinggal start cluster ABcluster (asadmin start-cluster ABcluster)
  9. Udah deh… jalan…

Clustering udah jalan, sekarang tinggal mainan load balancer-nya. Nah dari penjelasan di website-nya sun, bilang kalau ada beberapa cara buat load balancer webnya. Salah satunya yang paling mudah pakai apache. Kebutuhannya adalah

  • Web server apache. Disini penulis pake yang versi 2.2.4.
  • Modul mod_jk buat koneksi ke glassfish. Modul ini terkoneksi menggunakan standar ajp, biasa untuk mengkoneksikan apache dengan backend tomcat. Penulis pake versi mod_jk-1.2.26-httpd-2.2.6.so. Sebenarnya ada lagi modul yang pake protokol ajp ini, mod_proxyajp kalo gak salah, cuman yang memang lagi aktif ya mod_jk ini.
  • Library jar tomcat-ajp.jar , common-logging.jar, commons-modeler.jar buat ditaruh di glassfish.

Langkah-langkahnya :

  1. Masukkan modul mod_jk ke konfigurasi apache.
  2. Tambahkan konfigurasi di apachenya sbb:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <IfModule mod_jk.c>
    # Tells the module the location of the workers.properties file
    JkWorkersFile /etc/apache2/mods-available/workers.properties
    # Specifies the location for this module's specific log file
    JkLogFile /var/log/mod_jk.log
    JkShmFile /var/log/jk-runtime-status
    # Sets the module's log level to info
    JkLogLevel info
    # Sets the module's log time stamp format
    JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
    # JkOptions for SSL
    JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
    </IfModule>
  3. Buat file workers.properties di lokasi yang tunjuk dari konfigurasi sebelumnya. Disini penulis pake dua host A (192.168.1.133) dan host B (192.168.1.220).
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    worker.list=loadbalancer
    worker.worker1.type=ajp13
    worker.worker1.host=192.168.1.133
    worker.worker1.port=8009
    worker.worker1.lbfactor=1
    worker.worker1.socket_keepalive=1
    worker.worker1.socket_timeout=300
    worker.worker2.type=ajp13
    worker.worker2.host=192.168.1.220
    worker.worker2.port=8009
    worker.worker2.lbfactor=1
    worker.worker2.socket_keepalive=1
    worker.worker2.socket_timeout=300
    worker.loadbalancer.type=lb
    worker.loadbalancer.balance_workers=worker1,worker2
  4. Tambahkan mount point untuk direktori tertentu mengarah ke worker mod_jk (mis. JkMount /* loadbalancer). Dari contoh tersebut semua URL yang berawalan / akan mengarah ke worker milik mod_jk.
  5. Masukkan file-file jar ke direktori library milik glassfish (mis. /opt/glassfish/lib). Tambahkan parameter -Dcom.sun.enterprise.web.connector.enableJK=8009 di JVM Option (config cluster).
  6. Restart apache dan glassfish.

admin Server

Progres di blogdetik.com…

April 21st, 2008

Setelah mendeploy arsitektur baru blogdetik di mesin server yang baru, masih ada kendala yang dihadapi. Yang awal tampak adalah penggunaan session di WPMU. Session disimpan di server memcached dengan model replication, dimana jika salah satu server mati, akan switch fail over ke server satunya. Sebenarnya alokasi server memcached ini aslinya akan dipakai untuk aplikasi lainnya yang membutuhkan cache data, tapi untuk sementara ini dipakai buat blogdetik. Perkiraan awal meleset karena fail over menggunakan ucarp masih belum pas. Jika server master proses mati, tidak akan mentrigger fail over ke server slave. Untuk itu, harus dikendalikan sendiri dari sisi aplikasi. Untuk itu, harus ada tambahan script untuk menghandle session store diluar default session store milik memcache.

Disela-sela development, ditemukan masalah lain yang berhubungan dengan session. Salah satunya adalah plugin LDAP untuk authentication. Ada sedikit vulnerability dari validasi user. Cookie yang dibuat untuk validasi (wordpressuser dan wordpresspass) masih rentan terhadap serangan. Setelah memantau di kodenya, rupanya cookie pass diset menggunakan md5 username dan md5 ldap cookie marker, yang jelas kelihatan rentan untuk ditembus. Seharusnya representasi password benar-benar dari entitas password itu sendiri. Seperti di standar WPMU, validasi menggunakan md5 password yang dipassing ke cookie. Jadi setiap pemanggilan URL ke aplikasi, validasi dilakukan dengan pengecekan md5 password yang tersimpan diserver. Standar WPMU menyimpannya di file cache. Ini juga menimbulkan pertanyaan, kenapa tidak bermain-main dengan variable session. Disini penulis mulai mengupas pemakaian session di WPMU.

Ditemukan lagi pertanyaan, kenapa untuk masing-masing subdomain dari blogdetik harus membuat session lagi ? Kenapa gak dijadikan satu saja ? Disini lagi-lagi penulis coba untuk melihat penyebabnya. Dan… gak ketemu pastinya, tapi secara default WPMU rupanya tidak terlalu fokus untuk masalah ini. Okelah, sepertinya sekalian aja dirapikan untuk masalah session ini. Penulis berusaha menggunakan fasilitas variabel session yang ada di PHP. Untuk lebih meningkatkan sekuriti, akhirnya dipakailah variabel session untuk menyimpan md5 password (ini untuk meminimalisir load pengecekan ke database LDAP setiap pemanggilan URL).

Oh, ya; sebelumnya juga ditemukan masalah di plugin firestats. Plugin ini rupanya membuat mekanisme handling session sendiri diluar standar. Firestats memakai file based session, yang untuk sementara direktori dialihkan ke NFS server untuk sentralisasi. Akhirnya untuk sekalian menyeregamkan pemakaian session, penulis juga harus merubah management session ke satu bentuk management session di memcached.

Hasilnya, session management dibuat fasilitas fail-over. Dengan tambahan jika memang kedua server memcached sedang bermasalah, akan dialihkan ke cadangan file based session yang disimpan di direktori NFS mounted. Metode persistent connection gak berjalan mulus di server memcached. Ini ada hubungannya dengan php-cgi dalam menghandle exception untuk koneksi memcached yang bermasalah. Setelah mengganti ke bentuk non persistent, error gateway time out dikarenakan php-cgi yang bermasalah tidak terjadi lagi. Tapi konsekuensinya adalah banyaknya status koneksi time-wait. Untuk menghindarinya, set 1 ke parameter kernel tcp_tw_recycle & tcp_tw_reuse.

Selain itu semua subdomain di blogdetik menggunakan satu domain (.blogdetik.com). Dengan begitu sesi cookie akan kelihatan lebih bersih aja dibandingkan sebelumnya. Firestats plugin mendukung variabel memcached-based session.

Beberapa perbaikan kecil juga dilakukan di konfigurasi nginx.conf. Yakni masalah pemanggilan direktori (seperti wp-admin) tanpa “/”, yang mengakibatkan kesalahan pembuatan link di administrator panel. Solusinya harus redirect URL dengan penambahan “/” diakhir, jika URL memang adalah direktori. Masalah lain adalah set default comment_registration saat create user baru, untuk mencegah spam comment untuk non-user blogdetik. Feature supercache dan wp-cache juga di ulas kembali untuk kasus kontak. Penyelesainnya dengan cara memasukkan URL tersebut di daftar excluded URL di administrasi supercache dan wp-cache.

Berikut file-file yang mengalami perubahan dengan detil masalahnya:

  1. remove redundant session (wp-config.php) => change index.php, captca.php, kontak.php, wp-cache-config.php (add kontak.php as no cache)
  2. fix nginxmu.conf for redirecting directory access.
  3. fix password cookie (wp-settings.php (avoid clears GLOBAL var), ldap_auth.php(authorization/update pass;set session), wp-login.php (logout;clear session and sessionid)).
  4. create session memcached failover file based (failover seem trouble, cause persistent connection from memcache) => use manual if both servers down => use non persistent, then no need manual failover for file.
  5. session firestats used default php session => plugin/firestats/php/session.php
  6. set comment_registration 1 as default (wp-admin/includes/schema.(original|innodb).php)

Tapi masih ada todo list untuk masalah lainnya yang masih belum selesai, yakni:

  1. php-cgi fault.
  2. captca vulnerability.
  3. unknown directory created.
  4. yahoo mail problem.
  5. software monitoring.
  6. mobile themes.

admin General, Server

Benchmark XCache

March 31st, 2008

Di blogdetik.com sudah terinstall xcache. Cuman waktu itu gak ngeliat performance enhancement yang significant. Karena lagi nganggur, coba-coba testing lagi pake ab dengan jumlah request 100000 dan konkurensi 1. Konkurensi gak diset banyak, karena memang buat ngecek dari sisi loading script php-nya aja, apa bener sih opcode cache benar-benar bekerja maksimal. Waktu pertama ditest tanpa xcache, memori yang dikonsumsi webserver hanya 9-10Mbs (php-cgi). Hasil benchmark ab-nya:

Concurrency Level:      1
Time taken for tests:   12344.642804 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      1460381792 bytes
HTML transferred:       1398600000 bytes
Requests per second:    8.10 [#/sec] (mean)
Time per request:       123.446 [ms] (mean)
Time per request:       123.446 [ms] (mean, across all concurrent requests)
Transfer rate:          115.53 [Kbytes/sec] received

Sedangkan kalo dipasang xcache, memori yang dikonsumsi webserver 12-22Mb (php-cgi). Hasil benchmark-nya:

Concurrency Level:      1
Time taken for tests:   5754.861240 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      1460381652 bytes
HTML transferred:       1398600000 bytes
Requests per second:    17.38 [#/sec] (mean)
Time per request:       57.549 [ms] (mean)
Time per request:       57.549 [ms] (mean, across all concurrent requests)
Transfer rate:          247.82 [Kbytes/sec] received

admin Benchmark, Server

Session…. Memcached….

March 31st, 2008

Yah, hari ini ngerjain session management via memcached. Karena gak yakin kalo server ini bila dipake lebih dari satu aplikasi webserver gak akan crash key (session_id) yang dipake, maka satu-satunya cara adalah nambahin parameter web_id di php.ini bagian session.save_path. Biar tiap aplikasi assign web_id sendiri-sendiri. Jadi kemungkinan tiap aplikasi web server yang generate session_id (yang dipake sebagai key di memcached) + web_id gak akan pernah sama. Berikut sedikit patch di source memcache_session.patch.

admin Server