Load Balancing Strategy & Multiple Instances
Menjalankan beberapa instance aplikasi, memilih algoritma load balancing, mengelola session, dan menjaga koneksi database.
Load balancing membagi trafik ke beberapa instance agar aplikasi lebih tahan beban dan tidak bergantung pada satu proses.
Mengapa multiple instance?
- Throughput lebih tinggi.
- Failover jika satu instance mati.
- Deployment rolling/zero-downtime.
- Isolasi kegagalan lebih baik.
Aplikasi harus stateless
Instance aplikasi sebaiknya tidak menyimpan state lokal.
| State | Solusi |
|---|---|
| Session login | Redis/database |
| Upload file | Object storage |
| Cache | Redis |
| Job queue | Redis/RabbitMQ |
| Log | stdout + log collector |
Dengan stateless, request bisa dilayani instance mana pun.
Algoritma load balancing
| Algoritma | Cara | Cocok untuk |
|---|---|---|
| Round robin | Bergiliran | Instance homogen |
| Least connections | Ke yang paling sedikit koneksi | Request bervariasi |
| IP hash | Berdasarkan IP client | Butuh sticky sederhana |
| Weighted | Bobot per server | Kapasitas berbeda |
| Random | Acak | Skala besar |
Nginx round robin (default)
upstream app_backend {
server 10.10.10.11:3000;
server 10.10.10.12:3000;
}Least connections
upstream app_backend {
least_conn;
server 10.10.10.11:3000;
server 10.10.10.12:3000;
}IP hash
upstream app_backend {
ip_hash;
server 10.10.10.11:3000;
server 10.10.10.12:3000;
}IP hash membuat client yang sama cenderung ke instance yang sama. Namun jika IP berubah (mobile network, proxy), session bisa hilang. Lebih baik gunakan session store terpusat.
Menjalankan dua instance dengan Compose
services:
app1:
image: ghcr.io/org/app:${IMAGE_TAG}
env_file: .env
ports:
- "127.0.0.1:3001:3000"
app2:
image: ghcr.io/org/app:${IMAGE_TAG}
env_file: .env
ports:
- "127.0.0.1:3002:3000"Nginx:
upstream app_backend {
least_conn;
server 127.0.0.1:3001 max_fails=3 fail_timeout=10s;
server 127.0.0.1:3002 max_fails=3 fail_timeout=10s;
}Deployment bertahap
- Deploy instance baru di port berbeda.
- Health check instance baru.
- Tambahkan ke upstream.
- Reload Nginx.
- Hapus instance lama setelah draining.
nginx -t && systemctl reload nginxReload Nginx tidak memutus koneksi lama.
Session dan sticky session
Jika terpaksa memakai sticky session:
upstream app_backend {
ip_hash;
server 10.10.10.11:3000;
server 10.10.10.12:3000;
}Namun solusi yang lebih baik:
// session disimpan di Redis
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
}));Database connection pool
Setiap instance membuka koneksi ke database. Dengan 5 instance dan pool 20, total koneksi bisa 100.
const pool = new Pool({
host: process.env.DB_HOST,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
});Hitung: jumlah instance × max pool harus di bawah batas database.
Terlalu banyak koneksi database
Menambah instance tanpa menurunkan pool dapat menghabiskan koneksi PostgreSQL/MySQL. Gunakan
PgBouncer atau turunkan max pool per instance.
Health check dan failover
server 10.10.10.11:3000 max_fails=3 fail_timeout=10s;Jika instance gagal beberapa kali, Nginx mengeluarkannya sementara. Pastikan health endpoint benar-benar mencerminkan kesiapan.
Scaling
| Arah | Cara |
|---|---|
| Vertikal | Tambah CPU/RAM |
| Horizontal | Tambah instance |
| Database | Read replica, pooling |
| Cache | Redis cluster/replica |
Horizontal scaling lebih fleksibel, tetapi menuntut aplikasi stateless dan koordinasi resource.
Praktik: uji distribusi
for i in $(seq 1 10); do
curl -s http://app.example.com/whoami
echo
doneEndpoint /whoami dapat mengembalikan hostname/instance ID untuk memastikan trafik terdistribusi.
Ringkasan
- Multiple instance meningkatkan kapasitas dan ketersediaan.
- Aplikasi harus stateless; session disimpan terpusat.
- Pilih algoritma sesuai karakter trafik.
- Perhitungkan connection pool saat menambah instance.
Selanjutnya
Bangun sistem tahan gagal di High Availability Architecture.