Weighted Load Balancing #
Weighted load balancing memungkinkan kamu mendistribusikan traffic secara tidak merata ke backend yang berbeda — sesuai dengan proporsi yang kamu tentukan. Backend dengan weight lebih tinggi mendapat lebih banyak request dibanding backend dengan weight lebih rendah.
Ini adalah fitur yang sangat berguna dalam banyak skenario: backend dengan kapasitas berbeda, canary deployment untuk rilis bertahap, blue-green deployment untuk zero-downtime upgrade, dan A/B testing traffic splitting.
Cara Kerja Weighted Distribution #
Konfigurasi: backend-1 (weight 3), backend-2 (weight 1)
Total weight: 4
backend-1 mendapat 3/4 = 75% traffic
backend-2 mendapat 1/4 = 25% traffic
Dari 8 request berturut-turut:
Req-1 → backend-1
Req-2 → backend-1
Req-3 → backend-1
Req-4 → backend-2
Req-5 → backend-1
Req-6 → backend-1
Req-7 → backend-1
Req-8 → backend-2
backend-1: 6 request (75%)
backend-2: 2 request (25%)
Konfigurasi Weight di Caddy #
Weight dikonfigurasi per-upstream menggunakan subdirektif to dengan blok:
example.com {
reverse_proxy {
# Format: to UPSTREAM { weight N }
to backend-1:3000 {
weight 3
}
to backend-2:3000 {
weight 1
}
}
}
Tiga Backend dengan Weight Berbeda #
example.com {
reverse_proxy {
# Server besar: 8 core, 32GB RAM
to primary-server:3000 {
weight 6
}
# Server medium: 4 core, 16GB RAM
to secondary-server:3000 {
weight 3
}
# Server kecil: 2 core, 8GB RAM
to tertiary-server:3000 {
weight 1
}
# Total weight 10:
# primary: 60% traffic
# secondary: 30% traffic
# tertiary: 10% traffic
}
}
Use Case 1: Canary Deployment #
Canary deployment adalah teknik merilis versi baru secara bertahap — hanya sebagian kecil traffic yang diarahkan ke versi baru lebih dulu untuk memvalidasi bahwa tidak ada masalah sebelum rilis penuh.
Tahap 1: Rilis awal — 5% traffic ke versi baru
v1 (weight 19) + v2 (weight 1) = 95%/5% split
Tahap 2: Setelah 1 jam tanpa error — naikkan ke 10%
v1 (weight 9) + v2 (weight 1) = 90%/10% split
Tahap 3: Setelah 2 jam tanpa error — naikkan ke 25%
v1 (weight 3) + v2 (weight 1) = 75%/25% split
Tahap 4: Setelah 4 jam tanpa error — naikkan ke 50%
v1 (weight 1) + v2 (weight 1) = 50%/50% split
Tahap 5: Rilis penuh — 100% ke versi baru
Hanya v2
Jika masalah ditemukan di tahap manapun: rollback ke 0% v2
# Tahap 1: 5% canary
example.com {
reverse_proxy {
to app-v1:3000 {
weight 19
}
to app-v2:3000 {
weight 1
}
lb_policy round_robin
health_uri /health
health_interval 10s
}
}
# Workflow canary deployment dengan Caddy Admin API
# Tahap 1: Deploy v2, kirim 5% traffic
cat > /tmp/canary-5pct.json << 'EOF'
{
"apps": {
"http": {
"servers": {
"srv0": {
"routes": [{
"handle": [{
"@type": "reverse_proxy",
"upstreams": [
{"dial": "app-v1:3000", "max_requests": 19},
{"dial": "app-v2:3000", "max_requests": 1}
]
}]
}]
}
}
}
}
}
EOF
# Atau lebih mudah: update Caddyfile dan reload
# Edit weight di Caddyfile, lalu:
sudo systemctl reload caddy # Zero-downtime config reload
Use Case 2: Blue-Green Deployment #
Blue-green deployment menggunakan dua environment identik (blue = production saat ini, green = versi baru):
Kondisi normal (100% blue):
blue (weight 1) = 100%
green (weight 0) = 0% (green tidak ada di config)
Sebelum switch (test green):
blue (weight 99) = 99%
green (weight 1) = 1% (test dengan traffic minimal)
Switch ke green (zero downtime):
blue (weight 0) = 0% (hapus dari config)
green (weight 1) = 100%
Jika masalah: rollback ke blue (ubah config kembali)
# Production: 100% blue
example.com {
reverse_proxy app-blue:3000
}
# ── Transisi ke green ──────────────────────────────────────────
# Step 1: Test green dengan 1% traffic
example.com {
reverse_proxy {
to app-blue:3000 {
weight 99
}
to app-green:3000 {
weight 1
}
health_uri /health
health_interval 10s
}
}
# Step 2: Switch penuh ke green (hapus blue)
example.com {
reverse_proxy app-green:3000 {
health_uri /health
health_interval 10s
}
}
Use Case 3: Gradual Traffic Migration (Old Server → New Server) #
Ketika kamu memigrasikan dari server lama ke server baru, weighted load balancing memungkinkan migrasi bertahap:
# Minggu 1: 80% server lama, 20% server baru
example.com {
reverse_proxy {
to old-server.example.com:3000 {
weight 4
}
to new-server.example.com:3000 {
weight 1
}
health_uri /health
health_interval 15s
}
}
# Minggu 2: 50-50 (setelah yakin server baru stabil)
example.com {
reverse_proxy {
to old-server.example.com:3000 {
weight 1
}
to new-server.example.com:3000 {
weight 1
}
health_uri /health
}
}
# Minggu 3: Migrasi selesai — hanya server baru
example.com {
reverse_proxy new-server.example.com:3000 {
health_uri /health
}
}
Use Case 4: A/B Testing #
app.example.com {
reverse_proxy {
# Versi A: desain lama (70% traffic)
to app-variant-a:3000 {
weight 7
}
# Versi B: desain baru yang diuji (30% traffic)
to app-variant-b:3000 {
weight 3
}
lb_policy round_robin
}
# Log untuk analitik A/B testing
log {
output file /var/log/caddy/ab-test.log
format json
}
}
Weighted + Health Check: Failover Otomatis #
Ketika backend dengan weight tinggi down, Caddy otomatis mendistribusikan ke backend yang sehat:
example.com {
reverse_proxy {
to primary:3000 {
weight 9
}
to fallback:3000 {
weight 1
}
health_uri /health
health_interval 5s
health_timeout 3s
health_status 200
}
}
Normal operation:
primary: 90% traffic
fallback: 10% traffic
Primary down:
primary: 0% traffic (unhealthy, di-skip)
fallback: 100% traffic (semua dialihkan!)
Caddy otomatis redistribute tanpa restart atau intervensi manual.
Menghitung Weight yang Tepat #
Contoh: Tim memiliki 3 server dengan spesifikasi berbeda
Server specs:
Server A: 8 core, 32GB RAM (high-end)
Server B: 4 core, 16GB RAM (medium)
Server C: 2 core, 8GB RAM (small)
Pendekatan berdasarkan CPU core:
A: 8 core
B: 4 core
C: 2 core
Total: 14 core
A weight: 8 → 8/14 = 57%
B weight: 4 → 4/14 = 29%
C weight: 2 → 2/14 = 14%
Sederhanakan dengan GCD (greatest common divisor):
GCD(8,4,2) = 2
A weight: 4
B weight: 2
C weight: 1
Total: 7 → sama proporsinya
example.com {
reverse_proxy {
to server-a:3000 {
weight 4 # ~57%
}
to server-b:3000 {
weight 2 # ~29%
}
to server-c:3000 {
weight 1 # ~14%
}
health_uri /health
health_interval 10s
}
}
Monitoring Weighted Distribution #
# Verifikasi distribusi dari access log
cat /var/log/caddy/access.log | \
jq -r '.request.remote_addr + " " + .upstream_addr' | \
awk '{count[$2]++} END {
total = 0
for (k in count) total += count[k]
for (k in count) printf "%s: %d requests (%.1f%%)\n", k, count[k], count[k]/total*100
}'
# Expected output:
# app-v1:3000: 950 requests (95.0%)
# app-v2:3000: 50 requests (5.0%)
# Lihat config upstream saat ini via Admin API
curl -s http://localhost:2019/config/ | jq \
'.apps.http.servers[].routes[].handle[].upstreams[] | {dial, weight: .max_requests}'
Weighted dengan first Policy — Primary/Fallback
#
Selain mendistribusikan traffic secara proporsional, kamu juga bisa menggunakan pola primary/fallback — traffic selalu ke primary kecuali primary down:
example.com {
reverse_proxy {
to primary-dc:3000 {
weight 1 # Selalu coba primary dulu
}
to fallback-dc:3000 {
weight 0 # Fallback: hanya menerima traffic jika primary down
}
# Gunakan lb_policy 'first' untuk primary/fallback
lb_policy first
# Health check untuk deteksi primary down
health_uri /health
health_interval 5s
health_timeout 3s
}
}
Pola ini sering digunakan untuk multi-datacenter failover — semua traffic ke DC utama, baru beralih ke DC backup jika DC utama tidak tersedia.
Ringkasan #
- Weighted load balancing mendistribusikan traffic secara proporsional — backend dengan weight lebih tinggi mendapat lebih banyak request.
- Konfigurasi weight menggunakan blok
to UPSTREAM { weight N }di dalam direktifreverse_proxy.- Canary deployment: mulai dengan weight kecil (1%) untuk versi baru, naikkan secara bertahap setelah memvalidasi tidak ada error.
- Blue-green deployment: gunakan weighted untuk test versi baru dengan traffic minimal sebelum switch penuh — zero-downtime dan mudah rollback.
- Ketika backend berbobot tinggi down, Caddy otomatis mendistribusikan traffic ke backend lain yang masih sehat — failover tanpa intervensi.
- Hitung weight berdasarkan kapasitas aktual server (CPU core, RAM) dan sederhanakan dengan GCD untuk angka yang lebih bersih.