Weighted Load Balancing

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 direktif reverse_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.

← Sebelumnya: IP Hash   Berikutnya: Active Health Check →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact