08 Feb 2011
Pada artikel ini, kita akan mengulas secara singkat perintah-perintah yang sering kita gunakan dalam Git. Tapi sebelum mulai, perlu kita pahami beberapa istilah sebagai berikut:
-
diff : perbedaan antara satu file dengan file lain
biasanya diff dilakukan terhadap satu file yang sudah berubah isinya
-
changeset : kumpulan diff
-
working folder : folder kerja kita, berisi file yang (mungkin) sudah berubah sejak commit terakhir
-
staging : tempat persiapan changeset yang akan dicommit
-
commit : snapshot dari posisi folder dan file pada waktu tertentu
-
tip : commit paling ujung
-
head : nama lain tip
-
branch : head yang diberi nama
-
HEAD : head yang sedang aktif
-
merge : menggabungkan lebih dari satu commit
Membuat Repository
Untuk bisa mulai bekerja, kita harus memiliki repository dulu. Ada dua kemungkinan, kita membuat repository baru, atau kita membuat clone dari repository yang sudah ada.
Keterangan |
Perintah |
membuat repository baru |
git init |
membuat repository baru di folder project-baru |
git init project-baru |
membuat repository untuk dishare |
git init –bare project-baru |
copy repository lain |
git clone repo-url |
pilihan format URL
file:///path/ke/repo : clone dari folder lokal
/path/ke/repo : clone dari folder lokal, menggunakan hard link
http://server/path/ke/repo : clone melalui protokol http
username@server:path/ke/repo : clone melalui protokol ssh
Bekerja dengan Git
Berikut ini adalah perintah yang dilakukan selama sesi coding.
Keterangan | Perintah
————————————————————————————————————————|—————————————–
Menambah file baru | git add namafile
Menghapus file | git rm namafile
Memasukkan perubahan di satu file ke staging area | git add namafile
memasukkan semua perubahan | git add .
memilih potongan kode yang akan dimasukkan | git add -p
memasukkan perubahan ke staging menggunakan menu | git add -i
melihat status perubahan file, mana yang masih di working dan mana yang sudah di staging | git status
mengeluarkan perubahan dari staging area | git reset – namafile
melihat perubahan yang belum dimasukkan ke staging area | git diff
melihat perubahan yang akan dicommit (sudah ada di staging area) | git diff –staged
melihat perubahan antara working folder dan commit terakhir | git diff HEAD
melihat file mana saja yang berubah | git diff –name-status abc123..def456
melakukan commit, editor akan diaktifkan untuk mengisi keterangan | git commit
melakukan commit, langsung mengisi keterangan | git commit -m “langsung isi keterangan di sini”
commit langsung semua perubahan, tanpa melalui staging | git commit -a
melihat commit history | git log
log lima commit terakhir | git log -5
log hanya menampilkan summary | git log –oneline
tampilkan commit summary dari semua branch dengan graph hubungan antar commit | git log –oneline –all –graph
membuat commit baru yang berkebalikan dengan (undo) commit terakhir | git revert HEAD
undo 2 commit terakhir | git revert HEAD~2
memindahkan HEAD ke commit-id yang diminta, staging disamakan dengan HEAD, working tetap seperti semula.
Ini adalah opsi defaultnya reset | git reset –mixed
memindahkan HEAD ke commit-id yang diminta, isi working dan staging disamakan dengan commit-id tersebut | git reset –hard commit-id
memindahkan HEAD ke commit-id yang diminta, staging dan working tidak disentuh. Tidak mengubah output git status | git reset –soft
membuat working dan staging sama dengan HEAD | git reset –hard
Bekerja paralel menggunakan branch
Branch memungkinkan kita bekerja secara paralel, misalnya ada tim yang menambah fitur, dan ada tim yang melakukan bug fix.
Keterangan |
Perintah |
membuat branch baru |
git branch namabranch |
pindah ke branch tersebut |
git checkout namabranch |
bikin branch sambil pindah |
git checkout -b namabranch |
membuat tracking branch untuk branch bugfix di origin |
git checkout –track origin/bugfix |
membuat tracking branch dengan nama berbeda dengan remote |
git checkout -b myfix origin/bugfix |
membandingkan branch satu dengan lainnya |
git diff master..fitur-xx |
membandingkan branch dengan titik awal branch tersebut |
git diff master…fitur-xx |
menggabungkan branch satu dengan lainnya |
git checkout branch-tujuan |
|
git merge branch-yang-mau-diambil |
Mengedit konflik : |
|
- edit konfliknya |
git add namafile-yang-konflik |
- remove markernya |
git commit -m “merge fitur-xxx ke master” |
membatalkan merge yang konflik |
git reset –hard |
Bekerja dengan remote
Interaksi dengan remote repository
Keterangan |
Perintah |
mendaftarkan remote repository |
git remote add namaremote url |
melihat daftar remote repository |
git remote -v |
menghapus remote repository |
git remote rm namaremote |
mengambil perubahan di remote |
git remote update |
mengambil perubahan di satu remote saja |
git remote update namaremote |
mengambil perubahan di remote, hapus branch di lokal yang sudah tidak ada di remote |
git remote update –prune |
mengambil perubahan sesuai refspec yang sudah dikonfigurasi |
git fetch namaremote |
mengambil perubahan kemudian dimerge ke branch lokal yang sesuai |
pull = fetch + merge |
|
git pull namaremote |
mengirim perubahan di lokal ke remote |
git push nama-remote nama-branch-lokal:nama-branch-remote |
mengirim perubahan di lokal ke remote, semua branch yang namanya bersesuaian akan dikirim |
git push nama-remote |
mengirim perubahan di branch lokal yang sedang aktif ke branch di remote dengan nama yang sama |
git push nama-remote HEAD |
menghapus branch di remote |
git push nama-remote :nama-branch-remote |
Demikianlah perintah-perintah Git yang kita gunakan sehari-hari. Melengkapi daftar perintah di atas, diagram berikut dapat membantu pemahaman kita tentang konsep dan operasi di Git.
01 Feb 2011
Project Setup dengan menggunakan Gradle dan Git
Hal pertama yang kita lakukan sebelum mulai bekerja tentunya adalah menyiapkan meja kerja dan peralatannya. Sama juga dengan mulai membuat aplikasi. Kita harus menyiapkan struktur folder, library dan framework, dan mengatur semuanya agar siap dikerjakan di meja kita, dalam hal ini IDE.
Di ArtiVisi, biasanya ini dikerjakan oleh programmer senior, yaitu Martinus atau saya sendiri. Kegiatan project setup ini tidak terlalu tinggi frekuensinya, karena biasanya coding project yang existing jauh lebih sering daripada memulai project baru.
Yang jarang dikerjakan biasanya cepat dilupakan. Inilah alasan utama saya menulis posting kali ini, sebagai pengingat buat diri sendiri. Selain itu, mudah-mudahan ada manfaatnya juga untuk para pembaca sekalian.
Sebagai gambaran, tipikal aplikasi di ArtiVisi menggunakan stack standar 2011. Jadi, project setup ini akan dibuat mengikuti stack standar tersebut.
Pertama kali, kita buat dulu projectnya. Satu aplikasi biasanya kita pecah menjadi beberapa komponen, yaitu :
-
Domain Model dan Service API : ini kita pisahkan untuk memudahkan distribusi ke aplikasi client. Perhatikan bahwa yang saya maksud client di sini bukanlah customer pembeli aplikasi, melainkan aplikasi di sisi hilir misalnya user interface yang dibuat dengan Swing. Di sisi client, tidak perlu ada detail implementasi. Cukup class-class domain seperti Produk, Kategori, dsb. Juga kita sediakan service interface, yaitu method yang bisa digunakan untuk menjalankan proses bisnis.
-
Implementasi Service : ini adalah implementasi dari service interface di atas. Implementasi biasanya hanya ada di sisi server. Jadi, jar yang dihasilkan project ini tidak kita distribusikan ke client
-
Konfigurasi : file konfigurasi seperti jdbc.properties, logback-test.xml, smtp.properties, dan setting-setting lain kita juga pisahkan ke project sendiri. Ini tujuannya untuk memudahkan deployment. Seperti kita tahu, biasanya ada beberapa environment seperti development di laptop programmer, testing server, dan production server. Dengan memisahkan konfigurasi, kita bisa menghindari mendeploy konfigurasi development ke server production. Yang perlu diperhatikan di sini, hibernate.cfg.xml dan applicationContext.xml bukanlah file konfigurasi. Itu adalah file aplikasi, walaupun bentuknya xml dan tidak perlu dikompilasi.
-
User Interface : kalau aplikasi desktop, ini hanya satu project saja. Atau mungkin dua dengan konfigurasinya. Tapi untuk web, biasanya kita pecah dua juga. Yang satu berisi source code java, satu lagi berisi aplikasi web. Dengan demikian, bila ada perubahan di controller, kita cukup deploy 1 jar, tidak perlu upload 1 war.
Sebagai ketentuan lain, biasanya nama package selalu kita awali dengan com.artivisi, dan struktur folder mengikuti standar Maven.
Mari kita mulai, berikut rangkaian perintah di linux untuk membuat struktur awal project.
mkdir -p project-contoh/com.artivisi.contoh.{config,domain,service.impl,ui.springmvc,ui.web}/src/{main,test}/{java,resources}
mkdir -p project-contoh/com.artivisi.contoh.ui.web/src/main/webapp/WEB-INF
Outputnya bisa kita lihat sebagai berikut
find .
.
./com.artivisi.contoh.service.impl
./com.artivisi.contoh.service.impl/src
./com.artivisi.contoh.service.impl/src/test
./com.artivisi.contoh.service.impl/src/test/java
./com.artivisi.contoh.service.impl/src/test/resources
./com.artivisi.contoh.service.impl/src/main
./com.artivisi.contoh.service.impl/src/main/java
./com.artivisi.contoh.service.impl/src/main/resources
./com.artivisi.contoh.domain
./com.artivisi.contoh.domain/src
./com.artivisi.contoh.domain/src/test
./com.artivisi.contoh.domain/src/test/java
./com.artivisi.contoh.domain/src/test/resources
./com.artivisi.contoh.domain/src/main
./com.artivisi.contoh.domain/src/main/java
./com.artivisi.contoh.domain/src/main/resources
./com.artivisi.contoh.ui.springmvc
./com.artivisi.contoh.ui.springmvc/src
./com.artivisi.contoh.ui.springmvc/src/test
./com.artivisi.contoh.ui.springmvc/src/test/java
./com.artivisi.contoh.ui.springmvc/src/test/resources
./com.artivisi.contoh.ui.springmvc/src/main
./com.artivisi.contoh.ui.springmvc/src/main/java
./com.artivisi.contoh.ui.springmvc/src/main/resources
./com.artivisi.contoh.config
./com.artivisi.contoh.config/src
./com.artivisi.contoh.config/src/test
./com.artivisi.contoh.config/src/test/java
./com.artivisi.contoh.config/src/test/resources
./com.artivisi.contoh.config/src/main
./com.artivisi.contoh.config/src/main/java
./com.artivisi.contoh.config/src/main/resources
./com.artivisi.contoh.ui.web
./com.artivisi.contoh.ui.web/src
./com.artivisi.contoh.ui.web/src/test
./com.artivisi.contoh.ui.web/src/test/java
./com.artivisi.contoh.ui.web/src/test/resources
./com.artivisi.contoh.ui.web/src/main
./com.artivisi.contoh.ui.web/src/main/java
./com.artivisi.contoh.ui.web/src/main/webapp/WEB-INF
./com.artivisi.contoh.ui.web/src/main/resources
Berikutnya, kita lengkapi dengan dependensi jar. Di ArtiVisi, kita menggunakan Gradle.
Gradle meminta kita untuk mendaftarkan project yang terlibat dalam settings.gradle
include "com.artivisi.contoh.config"
include "com.artivisi.contoh.domain"
include "com.artivisi.contoh.service.impl"
include "com.artivisi.contoh.ui.springmvc"
include "com.artivisi.contoh.ui.web"
Dan ini build file Gradle.
springVersion = "3.0.5.RELEASE"
springSecurityVersion = "3.0.5.RELEASE"
slf4jVersion = "1.6.1"
logbackVersion = "0.9.27"
jodaTimeVersion = "1.6.2"
sourceCompatibility = 1.6
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
configurations {
all*.exclude group: "commons-logging", module: "commons-logging"
}
repositories {
mavenCentral()
}
dependencies {
compile "org.slf4j:jcl-over-slf4j:$slf4jVersion",
"org.slf4j:jul-to-slf4j:$slf4jVersion"
runtime "joda-time:joda-time:$jodaTimeVersion"
runtime "ch.qos.logback:logback-classic:$logbackVersion"
testCompile 'junit:junit:4.7'
}
group = 'com.artivisi.contoh'
version = '1.0-SNAPSHOT'
sourceCompatibility = 1.6
task wrapper(type: Wrapper) {
gradleVersion = '0.9.1'
jarFile = 'wrapper/wrapper.jar'
}
}
project('com.artivisi.contoh.domain') {
dependencies {
compile "org.hibernate:hibernate-entitymanager:3.4.0.GA"
compile "org.springframework:spring-tx:$springVersion",
"org.springframework:spring-orm:$springVersion",
"org.springframework:spring-jdbc:$springVersion"
}
}
project('com.artivisi.contoh.service.impl') {
dependencies {
compile project(':com.artivisi.contoh.domain')
compile "org.hibernate:hibernate-entitymanager:3.4.0.GA"
compile "org.springframework:spring-tx:$springVersion",
"org.springframework:spring-orm:$springVersion",
"org.springframework:spring-jdbc:$springVersion"
}
}
project('com.artivisi.contoh.ui.springmvc') {
dependencies {
compile project(':com.artivisi.contoh.service.impl')
compile "org.springframework:spring-webmvc:$springVersion",
"org.springframework:spring-aop:$springVersion"
compile "org.springframework.security:spring-security-web:$springSecurityVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion"
compile "javax.validation:validation-api:1.0.0.GA",
"org.hibernate:hibernate-validator:4.0.2.GA"
}
}
project('com.artivisi.contoh.ui.web') {
apply plugin: 'war'
apply plugin: 'jetty'
dependencies {
compile project(':com.artivisi.contoh.ui.springmvc')
runtime project(':com.artivisi.contoh.config')
runtime "javax.servlet:jstl:1.1.2",
"taglibs:standard:1.1.2",
"opensymphony:sitemesh:2.4.2"
providedCompile "javax.servlet:servlet-api:2.5"
}
}
Build file ini sudah mendeskripsikan semua sub-projectnya. Sebetulnya kita bisa membuat buildfile di masing-masing project, tapi saya lebih suka terpusat seperti ini supaya terlihat keterkaitan antar project.
Karena saya menggunakan Eclipse, saya menambahkan metadata supaya projectnya bisa dibuka di Eclipse. Ini bisa kita lakukan dengan cara menjalankan perintah
dalam masing-masing folder project. Tapi karena terlalu malas, saya gunakan satu baris perintah ini.
for d in */; do cd "$d"; gradle eclipse; cd ..; done
Untung saja pakai linux, jadi bisa coding di command prompt :D
Selanjutnya, kita bisa test dengan melakukan build di project paling hilir, yaitu ui.web
cd com.artivisi.contoh.ui.web
gradle war
Hasilnya ada di folder build/libs
Kita cek apakah semua dependensi sudah terpenuhi dengan perintah berikut.
jar tvf build/libs/com.artivisi.contoh.ui.web-1.0-SNAPSHOT.war
Ini juga bisa langsung dijalankan dengan plugin Jetty yang ada dalam Gradle.
cd com.artivisi.contoh.ui.web
gradle jetty
Outputnya bisa kita lihat di browser, dengan port 8080.
Di situ ada link menuju aplikasi kita. Silahkan diklik.
Folder WEB-INF masih terlihat, karena kita belum membuat web.xml. Berikut isi web.xml, masukkan dalam folder com.artivisi.contoh.ui.web/src/main/webapp/WEB-INF
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Reads request input using UTF-8 encoding -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Handles all requests into the application -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/springmvc-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Sekalian saja kita konfigurasi Spring MVC. Pasang file springmvc-context.xml ini di sebelahnya web.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="com.artivisi.contoh.ui.web" />
<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />
<!-- mengganti default servletnya Tomcat dan Jetty -->
<!-- ini diperlukan kalau kita mapping DispatcherServlet ke / -->
<!-- sehingga tetap bisa mengakses folder selain WEB-INF, misalnya img, css, js -->
<mvc:default-servlet-handler/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages" />
<property name="cacheSeconds" value="0" />
</bean>
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/templates/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- Forwards requests to the "/" resource to the "hello" view -->
<mvc:view-controller path="/" view-name="hello"/>
</beans>
Kita cek juga apakah projectnya sudah bisa dibuka di Eclipse. Mari kita import.
Pertama, arahkan workspace ke folder project-contoh.
Setelah Eclipse terbuka, kita pilih menu Import Project, untuk membuka 4 project yang tadi sudah kita buat.
Pilih folder induknya.
Selesai, semua project kita bisa dibuka. Bahkan kita bisa menjalankan project ui.web dengan cara klik kanan Run in Server. Ini bisa dilihat dari icon project tersebut yang berbentuk bola dunia.
Selesai sudah, mari kita share dengan rekan yang lain.
30 Jan 2011
Di milis JUG, lagi-lagi ada yang tanya tentang load balancing, failover, dan clustering. Jawabannya masih sama sejak 10 tahun saya berkecimpung di urusan coding-mengcoding. Jadi, baiklah saya tulis di blog saja, supaya next time bisa jadi referensi.
Ini sebetulnya dua hal yang berbeda.
Load balancing ya membagi beban.
Failover ya mencegah single point of failure.
Load Balancing
Load balancer terdiri dari satu balancer dan banyak worker.
Bebannya dibagi2 ke semua worker dengan algoritma yang biasanya bisa dipilih.
Bisa merata (round robin) bisa juga dengan bobot (weighted), misalnya worker X mendapat 2 kali worker Y karena dia specnya lebih tinggi.
Atau bisa juga dynamic, artinya si LB akan mengetes kondisi semua worker, mana yang kira2 sedang idle itu yang dikasi.
Mana yang sedang idle ini nanti ada lagi settingnya, apakah melihat CPU usage pakai SNMP, melihat ping response time, whatever.
Failover minimal harus ada 2 titik.
Kalo kita implement LB aja, point of failure (POF) nya adalah si LB.
Begitu LB nya mati, ya udah semua worker gak bisa diakses.
Untuk mencegah ini, LB nya harus ada 2, satu aktif satu standby (pasif).
Contoh aplikasi load balancer :
- HAProxy
- ldirectord (Ultra Monkey)
- Pound
Contoh aplikasi lain yang bisa jadi load balancer :
- Apache (mod_proxy_balancer)
- Nginx
- lighttpd
- bind (DNS Server)
Failover
Contoh aplikasi failover :
Failover artinya mengatasi kalau ada service yang mati. Ada dua jenis aplikasi untuk menangani failover :
- Network Oriented : keepalived, ucarp
- Cluster Oriented : corosync, heartbeat
Penjelasan lengkapnya bisa dibaca di sini. Namun ringkasnya seperti ini:
Network oriented failover memastikan minimal satu service aktif, dan tidak apa-apa bila ada lebih dari satu service yang aktif. Ini cocok untuk dipasang di load balancer, karena load balancer tidak menyimpan state. Tidak masalah kalau user melihat ada dua LB, kadang diarahkan ke LB-1 dan kadang ke LB-2.
Cluster oriented failover memastikan hanya satu service yang aktif, dan tidak apa-apa bila tidak ada service yang aktif. Ini cocok untuk dipasang di database server, karena kita tidak mau database utama dan cadangan dua-duanya aktif. Bisa-bisa datanya tidak tersimpan dengan benar (split brain). Untuk lebih jelas tentang cara kerja cluster-oriented failover, bisa dibaca di sini.
Nah, mudah2an sampe di sini jelas bahwa load balancing dan failover itu dua hal yang tidak saling terkait (orthogonal) dan biasanya dikombinasikan untuk mendapatkan konfigurasi yang robust dan performant.
Setahu saya konsep2x Clustering diatas berlaku pada saat hit pertama.
Pertanyaan saya.. Bagaimana jika request sudah terlayani tetapi ditengah-tengah proses server tiba2x down.. Apakah proses tersebut langsung di alihkan ke server yang lagi up? Jika iya apakah proses akan di restart dari awal atau server yang sedang up bisa melanjutkan sisa dari proses yang belum dikerjakan di server yang telah down?
Sticky Session
Tidak selalu, tergantung konfigurasinya.
Ada konfigurasi sticky session.
Artinya, pada hit pertama, si user akan diberikan penanda, biasanya berbentuk cookie.
Pada hit berikutnya, LB akan melihat cookienya, dan mengarahkan ke server yang sebelumnya sudah mengurus si user ini.
Ada juga konfigurasi non-sticky.
Artinya tiap hit dianggap hit baru, dan didistribusikan ke semua server sesuai algoritma yang dipilih, round robin, weighted, atau dynamic, sesuai penjelasan di atas.
Mau pilih yang mana? Ya tergantung kemampuan LB nya.
Ada yang bisa 2-2 nya sehingga bisa pilih, dan ada juga yang rada stupid sehingga terpaksa pakai non-sticky.
Istilahnya, LBnya layer berapa? Kalo layer 7 biasanya bisa sticky, kalo layer 4 ya gak bisa.
Lebih jauh tentang urusan layer-layeran ini bisa dibaca di sini dan di sini
Nah, apa impact sticky vs non-sticky?
Ini pengaruhnya ke session data.
Session data adalah data sementara masing-masing user.
Karena sifatnya sementara, maka biasanya tidak disimpan secara persistent di tabel database.
Contoh paling klasik adalah isi shopping cart.
Itu barang belum diorder, tapi sudah dipilih, sehingga biasanya belum disimpan di database.
Kalo pake non-sticky, si user pertama milih barang di server X.
Pada saat dia pilih barang kedua, dilayani server Y.
Karena pilihan pertama ada di server X, ya pas dia pilih barang kedua, cuma tercatat 1 barang padahal harusnya 2.
Ini tidak terjadi kalo kita pakai sticky balancer.
Request kedua dan seterusnya akan diarahkan ke server X lagi.
Jadi, sticky atau non-sticky itu impactnya ke temporary data user, sering disebut dengan istilah session data atau user state.
Nah, setelah jelas apa dampaknya sticky vs non-sticky, mari kita lanjut ke pertanyaan selanjutnya.
Kalau untuk Java EE Application Server apakah untuk pertanyaan saya di atas sudah ada featurenya atau perlu ada tambahan produk lagi untuk bisa sharing informasi terhadap state suatu proses yang dijalankan di satu server sehingga jika server tersebut down proses bisa dilanjutkan di server yang lain tanpa merestart proses?
Session Replication
Mengenai urusan session/state management, ini sangat tergantung merek application server yang digunakan.
Secara umum, settingan standar appserver biasanya simpan data session di memori.
Kalau kita enable cluster, misalnya terdiri dari 4 worker, maka data session ini biasanya akan direplikasi ke satu worker lain.
Pada saat worker utama mati, request berikutnya akan diarahkan ke worker cadangannya, sehingga user gak kehilangan data belanjaan.
Biasanya, satu state itu disimpan ke 2 worker saja, bukan direplikasi ke semua untuk alasan efisiensi bandwidth.
Pada penjelasan di atas banyak sekali saya gunakan kata ‘biasanya’. Ini karena kapabilitas dan konfigurasi masing-masing merek appserver sangat berbeda sehingga sulit untuk menggeneralisir kondisinya.
Lalu bagaimana?
Saya biasanya mengambil pendekatan yang universal, yang jalan di semua appserver, sehingga tidak perlu pusing menghafal appserver apa bisa apa settingnya gimana.
Teknik universalnya sederhana: aplikasi webnya dibuat stateless.
Jangan ada simpan data di memori. Simpan semua di database, atau di distributed cache (misalnya memcached).
Di Java, data yang ada di memori antara lain : session variable, static variable, context variable.
Di PHP, CMIIW cuma session dan global variable aja.
Karena selama ini saya menggunakan teknik ini, jadi saya kurang up to date terhadap appserver apa bisa apa settingnya gimana.
Demikian juga tentang load balancer apa support sticky atau tidak, saya tidak pernah memikirkannya.
Pokoknya simpan state di distributed cache atau database, setelah itu mau pakai appserver Tomcat, Jetty, Glassfish, Weblogic, terserah.
Mau pakai load balancer Apache HTTPD, Nginx, lighty, HAProxy, Pound, Ultramonkey, juga terserah.
Demikian sekilas sharing mengenai load balancing dan clustering. Semoga menjadi cerah.
25 Jan 2011
Posting ini adalah update dari posting tiga tahun yang lalu. Tidak banyak yang berubah dalam stack ini, yang bisa berarti dua hal: pilihan tiga tahun yang lalu sudah tepat atau malas belajar selama 3 tahun ini.
Mudah-mudahan alasannya yang pertama :D
Update : Gradle tidak jadi dipakai, karena kita tidak mau maintain 2 skillset. Maven 2 ternyata stabil dan bekerja sesuai harapan. Hudson terlibat kerusuhan dengan Oracle, akhirnya fork jadi Jenkins.
Presentation Layer
-
Spring MVC
-
SiteMesh
-
Dojo Toolkit
-
ExtJS
-
Spring Security
-
Jasper Report
-
Jackson
Business Layer
-
Spring Framework
-
Hibernate
Library lain yang sering digunakan
-
Logback
-
Joda Time
-
Velocity
-
JPos
Infrastruktur
-
Version Control : Git + Gitosis
-
Testing Tools : JUnit, DBUnit, JMeter, Sonar
-
Issue Tracker : Redmine
-
Build Tools : Gradle, Maven
-
Continuous Integration : Hudson Jenkins
-
OS Programmer : Ubuntu Desktop
-
OS Server : Ubuntu Server, Debian
Deployment Target
-
Database Server : MySQL, Oracle
-
Application Server : Tomcat, Glassfish
Praktis perubahan yang terjadi hanyalah dari Subversion ganti menjadi Git.
Nah, bagaimana menurut Anda? Pilihan tepat atau malas belajar?
11 Jan 2011
Skenario : selama ini kita coding di laptop sendiri saja. Kemudian ada kebutuhan untuk kolaborasi dengan orang lain melalui Git. Bagaimana caranya? Baiklah mari kita bahas di artikel ini.
Inisialisasi Repository Git
Pertama, kita inisialisasi dulu repository Git. Masuk ke dalam folder project dan ketikkan
Git akan membuat repository kosong di dalam folder project, ditandai dengan adanya folder baru bernama .git
Selanjutnya, kita akan memasukkan semua file dan folder project kita ke dalam repository. Yang harus dimasukkan adalah file source code, baik itu Java, HTML, XML, dan sebagainya. Yang tidak perlu dimasukkan adalah file hasil kompilasi atau hasil generate. Kita perlu mendaftarkan file yang tidak ingin disimpan dalam file konfigurasi yang bernama .gitignore
File ini harus kita buat sendiri menggunakan text editor. Berikut contoh isi filenya, bila kita coding menggunakan Eclipse atau Netbeans
[gist id=773975]
Setelah kita setting ignore file, berikutnya kita masukkan semua file dan folder ke dalam antrian.
Kemudian, simpan ke repository
git commit -m "commit pertama project XXX"
Project sudah tersimpan di repository Git di komputer lokal kita. Mari kita upload ke server, atau dikenal dengan istilah push.
Share Repository
Kita memerlukan server di mana kita memiliki ijin akses untuk melakukan push. Cara memperoleh ijin akses tidak dibahas pada artikel ini. Silahkan buat account di Github atau Gitorious. Bila ingin push ke repository perusahaan, minta informasinya pada admin Anda.
Setelah kita mendapatkan URL server yang bisa kita gunakan, daftarkan sebagai remote. Berikut perintahnya.
git remote add <namaremote> <URL>
Contohnya seperti ini
git remote add github git@github.com:endymuhardin/project-terbaru-saya.git
Pastikan remotenya sudah terdaftar dengan perintah berikut
Terakhir, mari kita push dengan perintah berikut
git push <namaremote> <namabranch>
Contohnya
Hore, project kita sudah naik ke server. Kita tinggal share URL tersebut ke rekan kerja kita.