Just small script for toying around with python….

May 12th, 2009

There is always a first time… now this is it.. in English coi…. :D
It happened during administrating servers in detik. Every time doing login to the servers, it always ask the password. There’s mechanism by copying public key into remote server in order to login automatically without entering the password. Application like ssh-copy-id do the job.
So, my concern is how to do login automatically without having explicitly launch ssh-copy-id before ssh to the server. I’ve written a script to handle that. This script requires pexpect library. Here it is :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"""
USAGE:

go user@host

This script is used as One Time Password SSH login
"""


import os, pexpect, getpass, sys, socket
def gethomedir():
    for user in open('/etc/passwd'):
        cols = user.split(':')
        if cols[0] == os.getlogin():
            return cols[5]

def knownhost(user_host):
    for line in open(homedir + '/.ssh/hosts', 'a+'):
        if line.strip() == user_host:
            return True
    return False
           
def updateknownhost(user_host):
    fd = open(homedir + '/.ssh/hosts','a+')
    fd.write(user_host + '\n')
    fd.close()
   
if __name__ == "__main__":
    homedir = gethomedir()
    if not len(sys.argv) > 1 or sys.argv[1].find('@') < 0:
                print __doc__
                sys.exit(1)
   
    user,host = sys.argv[1].split('@')
    try:
        host = socket.gethostbyname(host)
    except socket.gaierror:
        print 'Error resolving host'
        sys.exit(1)
    if not knownhost(user + '@' + host):
        # ssh-copy-id and update info
        print 'Hostname %s | User %s' % (host, user)
        result = 0
        exp = pexpect.spawn('ssh-copy-id ' + sys.argv[1])
        while result != 2:
            result = exp.expect(['password', 'publickey,password', 'expecting', pexpect.EOF])
            if result == 0:
                # try again
                passwd = getpass.getpass('Enter Password:')
                exp.sendline(passwd)
            elif result == 1 or result == 3:
                # failed to input password correctly
                print 'Failed.'
                sys.exit(1)
        # update info
        updateknownhost(user + '@' + host)
        exp.close()
    os.system('ssh ' + ' '.join(sys.argv[1:]))

And also I’ve created small script to manipulate /etc/hosts, because sometime I don’t remember IP address of some servers, so I just need to create an alias in /etc/hosts. Here is the script :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
"""
USAGE:

hosts add address hostname... | del [address|hostname]...

This script adds/deletes hostname alias in /etc/hosts
"""


import os, getpass, sys, socket

lineread={}
linewrite={}

def addhosts(address, hostname):
        global linewrite, lineread
        notFound = True
        for idx, line in linewrite.iteritems():
                cols = filter(lambda x:not x == '', line.split())
                if cols[0] == address:
                        notFound = False
                        for host in hostname:
                                if not host in cols:
                                        cols.append(host)
                        linewrite[idx] = ' '.join(cols) + "\n"
        if notFound:
                lineread[len(lineread)] = address + ' ' + ' '.join(hostname) + "\n"

def delhosts(addr_host):
        global linewrite, lineread
        lw = linewrite.copy()
        isAddr = False
        for idx, line in lw.iteritems():
                cols = filter(lambda x:not x == '', line.split())
                for item in addr_host:
                        if item in cols:
                                if cols[0] == item:
                                        isAddr = True
                                        del linewrite[idx]
                                        del lineread[idx]
                                else:
                                        i = 1
                                        for col in cols[1:]:
                                                if col == item:
                                                        del cols[i]
                                                i+=1
                                        if len(cols) == 1:
                                                isAddr = True
                                                del linewrite[idx]
                                                del lineread[idx]
                if not isAddr:
                        linewrite[idx] = ' '.join(cols) + "\n"

if __name__ == "__main__":
        if not len(sys.argv) > 2 or not sys.argv[1] in ['add','del']:
                print __doc__
                sys.exit(1)

        idx=0
        try:
                for line in open('/etc/hosts'):
                        lineread[idx]=line
                        if not (line.strip().startswith('#')) and not (line.strip() == ''):
                                linewrite[idx]=line                    
                        idx+=1
        except IOError:
                print 'Error opening /etc/hosts'
                sys.exit(1)
       
        if sys.argv[1] == 'add':
                addhosts(sys.argv[2],sys.argv[3:])
        else:
                delhosts(sys.argv[2:])
       
        hosts = open('/etc/hosts','w')
        for idx, line in lineread.iteritems():
                if linewrite.has_key(idx):
                        hosts.write(linewrite[idx])
                else:
                        hosts.write(lineread[idx])

admin General

Menganalisa log mysqld.log

March 17th, 2009

Sekalian udah lama gak ngeblog.. sekarang ngisi lagi, meskipun gak penting… hahahaha…

Oke, terkait dengan aktifitas analisa log web di openx (ini seharusnya posting tersendiri lagi) untuk mengetahui response times dan request per seconds. Dari hasil log diketahui bahwa request yang paling lama responsenya (lebih dari 1 detik) adalah script-script yang menjalankan aktifitas database. Meskipun di lihat dari dokumentasi openx, sebenarnya request ke database di cache menjadi file, yang kemudian request-request selanjutnya yang sama akan mengambil di file. Tapi bagaimanapun juga, penulis masih penasaran, apa bener dia ngecache ke file, gak melakukan request yang sama berulang-ulang ke database.

Untuk itu penulis coba buat script pake python untuk analisa mysqld.log. Ini log yang mencatat aktifitas DML dan juga DDL. Penulis hanya tertarik pada request query SELECT saja, karena request inilah yang bisa dicache pake memcached nantinya. Tapi untuk mengetahui pasti, apa bener ada request SELECT yang sama berulang-ulang, yaaa…. pake script python ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import hashlib, sys
def readlines(fl,sep='\n'):
    line=''
    initial=0
    data=fl.read(1024)
    while data!='':
        possep=data.find(sep,initial)
        if possep==-1:
            line=line+data[initial:]
            possep=initial=0
            data=fl.read(1024)
        else:
            line=line+data[initial:possep]
            yield line
            line=''
            initial=possep+len(sep)
    if line!='':
        yield line

for line in readlines(open(sys.argv[1]),sep='\t\t'):
    pos = line.find('SELECT',0)
    if pos != -1:
        print hashlib.md5(line[pos:]).hexdigest()

Intinya parse per line query SELECT-nya, kemudian di md5sum. Dengan begitu keliatan jika md5sumnya sama, berarti querynya sama persis. Coba di test di satu hari saja.
Panggil parsemysql.py|wc -l, hasilnya 973954 baris. Setelah itu panggil parsemysql.py|uniq|wc -l, hasilnya 969174 baris.
Wadow… kok selisihnya gak jauh ya…. padahal berharap selisih banyak, biar bisa dioptimasi pake memcached. Ya udah…. pupus deh :( …. Berarti emang bener, request udah dicache di file oleh openx.

—- Updated —–
Blo’on…. keliru ternyata cara cari digest yang sama. Seharusnya di sort dulu, baru di uniq…. Semprul…
Percobaan kedua di lakukan; sama dengan sebelumnya, yang pertama panggil parsemysql.py|wc -l, hasilnya 1013913 baris. Setelah itu baru menghilangkan yang sama dengan cara parsemysql.py|sort|uniq|wc -l, hasilnya 20739 baris. Jauh banget euiii… kalo gini caranya, ya pake memcached dong….

admin General

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

Poison message di Message Driven Bean

May 7th, 2008

Sebenarnya solusinya agak sedikit kurang bagus sih untuk mengatasi masalah poison message di MDB ini, tapi bagaimana lagi….. Poison message itu sebenarnya message yang diterima oleh MDB dari JMS sedemikian rupa sehingga waktu diolah di MDB-nya membuat error di bisnis logic. Sehingga exception dilempar dan diketahui oleh container EJB, kemudian melakukan proses rollback transaction. Rollback transaction akan diikuti proses redelivery message oleh JMS ke recipent, dalam hal ini MDB itu sendiri. Jika itu berlanjut, maka otomatis proses akan berulang-ulang tanpa henti. Ini bisa menghabiskan load di server.

Nah, berhubung penulis masih belajar :D , maka salah satu solusinya (sesuai dengan yang dibuku sih) adalah dengan memberi penanda khusus untuk tiap message ID. Jadi jika proses sudah berulang kali dilakukan dengan message ID yang sama, maka jika sudah melebihi batas redelivery message count-nya, message akan di discard dan tidak masuk dalam bisnis logic. Dengan begitu MDB akan berjalan aman, gak akan terjadi pengulangan proses dengan message ID yang sama.

Tapi sebenarnya yang mengganjal itu adalah proses catch exception yang dikeluarkan oleh JDBC (pake JPA). Karena memang tidak tertangkap baik di sisi MDB-nya. Jadinya akal-akalan dengan melihat contoh kasus di forum, yang menggunakan entity manager untuk menyimpan ke DB; dengan cara setelah memanggil command persist, harus diikuti oleh command flush. Dengan begitu exception yang dikeluarkan di bisnis logic (khususnya di JPA-nya) dapat di catch. Meskipun penulis pikir yang ke catch itu EJBException-nya, soalnya sebelumnya dilihat di log, proses berulang-ulang itu akan throw 2 exception, satu adalah toplink JDBCnya dan EJBException sendiri (ini kayaknya bagian containernya).

Saat ini udah kehandle pake cara tadi itu, cuman ya itu tadi; belum ketemu untuk nge-catch Database Exceptionnya…. yah … sambil jalan aja lah…..

admin General

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