Weighted Load Balancing #

Weight memungkinkan kita mengontrol seberapa banyak traffic yang diterima setiap server secara proporsional. Secara default semua server memiliki weight 1 — distribusi merata. Dengan weight, kita bisa mencerminkan perbedaan kapasitas hardware, melakukan canary deployment bertahap, atau menjalankan strategi blue-green deployment zero-downtime.

Cara Kerja Weight #

Weight adalah angka relatif. Yang penting bukan nilainya secara absolut, melainkan perbandingan antar server:

upstream app_servers {
    server 10.0.0.1:3000 weight=3;
    server 10.0.0.2:3000 weight=1;
}

Dari setiap 4 request:

  • 3 request → Server 10.0.0.1 (weight 3)
  • 1 request → Server 10.0.0.2 (weight 1)

weight=3 dan weight=1 menghasilkan distribusi yang identik dengan weight=6 dan weight=2, atau weight=30 dan weight=10. Nginx mendistribusikan berdasarkan proporsi.

Tanpa weight (atau weight=1), semua server mendapat distribusi yang sama:

weight=1, weight=1, weight=1 → 33.3%, 33.3%, 33.3%
weight=2, weight=1, weight=1 → 50%,   25%,   25%
weight=3, weight=2, weight=1 → 50%,   33.3%, 16.7%
weight=5, weight=3, weight=2 → 50%,   30%,   20%

Use Case 1: Server dengan Kapasitas Hardware Berbeda #

Skenario paling umum dalam dunia nyata: infrastruktur yang terdiri dari server dengan spesifikasi yang tidak seragam — karena upgrade bertahap, warisan dari era sebelumnya, atau penggunaan spot instance:

upstream production_cluster {
    # Server generasi terbaru (high-end)
    # 32 core, 128GB RAM, SSD NVMe
    server 10.0.0.1:3000 weight=8;

    # Server generasi menengah
    # 16 core, 64GB RAM, SSD
    server 10.0.0.2:3000 weight=4;

    # Server lama yang masih digunakan
    # 8 core, 32GB RAM, HDD
    server 10.0.0.3:3000 weight=2;

    # Server minimal (backup yang ikut melayani traffic normal)
    # 4 core, 16GB RAM
    server 10.0.0.4:3000 weight=1;

    # Total: 15 bagian
    # Server 1: 8/15 = 53% traffic
    # Server 2: 4/15 = 27% traffic
    # Server 3: 2/15 = 13% traffic
    # Server 4: 1/15 = 7% traffic

    keepalive 32;
    zone production_upstream 128k;
}

Use Case 2: Canary Deployment #

Canary deployment adalah teknik merilis versi baru dengan mengirimkan sebagian kecil traffic terlebih dahulu untuk validasi sebelum full rollout. Weight adalah cara paling mudah mengimplementasikannya di Nginx:

flowchart LR
    subgraph PHASE1["Tahap 1: Canary 5%"]
        P1A["v1 weight=95\n(server 1, 2, 3)"]
        P1B["v2 weight=5\n(server 4) canary"]
    end

    subgraph PHASE2["Tahap 2: Lanjut ke 20%"]
        P2A["v1 weight=80\n(server 1, 2)"]
        P2B["v2 weight=20\n(server 3, 4)"]
    end

    subgraph PHASE3["Tahap 3: Full Rollout"]
        P3A["v2 weight=1\n(semua server)"]
    end

    PHASE1 --> PHASE2
    PHASE2 --> PHASE3
# Tahap 1: Mulai dengan 5% ke versi baru
upstream app_servers {
    server 10.0.0.1:3000 weight=95;  # v1 — production
    server 10.0.0.2:3000 weight=95;  # v1 — production
    server 10.0.0.3:3000 weight=10;  # v2 — canary (5% dari total)
}
# Cara mengubah weight tanpa downtime:
# 1. Edit konfigurasi
vim /etc/nginx/conf.d/myapp.conf

# Tahap 2: Naikkan ke 20%
# server 10.0.0.1:3000 weight=80;  # v1
# server 10.0.0.2:3000 weight=20;  # v2
# ...

# 2. Test konfigurasi
nginx -t

# 3. Reload tanpa downtime
nginx -s reload

Monitoring Canary dengan Logging #

http {
    # Map versi berdasarkan upstream server yang dipilih
    map $upstream_addr $app_version {
        "~10\.0\.0\.[12]:" "v1";
        "~10\.0\.0\.3:"    "v2-canary";
        default            "unknown";
    }

    log_format canary_log '$remote_addr [$time_local] "$request" '
                          '$status $app_version $upstream_response_time';

    server {
        access_log /var/log/nginx/canary.log canary_log;
    }
}
# Analisis error rate per versi
awk '{print $6, $5}' /var/log/nginx/canary.log | \
    awk '{total[$1]++; if($2>=500) err[$1]++} END {for(k in total) print k, err[k]+0, total[k], (err[k]+0)/total[k]*100"%"}' | \
    sort

# Output:
# v1         12  9823  0.12%
# v2-canary   8   489  1.63%  ← error rate tinggi, rollback!

Use Case 3: Blue-Green Deployment Zero-Downtime #

Blue-green deployment menjalankan dua lingkungan produksi (blue = versi lama, green = versi baru) dan switch traffic sekaligus:

upstream app_servers {
    # BLUE: versi yang saat ini aktif
    server 10.0.0.1:3000 weight=1;  # blue-1
    server 10.0.0.2:3000 weight=1;  # blue-2

    # GREEN: versi baru — siap tapi belum terima traffic
    server 10.0.0.3:3000 weight=0 backup;  # green-1
    server 10.0.0.4:3000 weight=0 backup;  # green-2
}

Saat switch: edit konfigurasi, aktifkan green, nonaktifkan blue:

upstream app_servers {
    # BLUE: dinonaktifkan
    server 10.0.0.1:3000 down;
    server 10.0.0.2:3000 down;

    # GREEN: sekarang menerima semua traffic
    server 10.0.0.3:3000 weight=1;
    server 10.0.0.4:3000 weight=1;
}

Jika ada masalah, rollback instan dengan membalik konfigurasi lagi dan nginx -s reload.


Kombinasi Weight dengan Algoritma Lain #

Weighted Least Connections #

upstream app_servers {
    least_conn;

    # Server kuat mendapat lebih banyak koneksi sebelum dianggap "sibuk"
    server 10.0.0.1:3000 weight=4;  # 16 core
    server 10.0.0.2:3000 weight=2;  # 8 core
    server 10.0.0.3:3000 weight=1;  # 4 core

    keepalive 32;
    zone app_upstream 64k;
}

Formula pemilihan: koneksi_aktif / weight — server dengan nilai terkecil dipilih. Server berkapasitas lebih besar “membutuhkan” lebih banyak koneksi sebelum dianggap lebih sibuk dari server kecil.

Weighted IP Hash #

upstream app_servers {
    ip_hash;

    # Session persistence + weight
    server 10.0.0.1:3000 weight=3;
    server 10.0.0.2:3000 weight=1;
}

Dengan ip_hash + weight, pengguna masih dijamin ke server yang sama, tapi distribusi user antar server memperhitungkan weight. Server dengan weight lebih tinggi mendapat lebih banyak “slot” dalam ring hash.


Strategi Penerapan Weight untuk Auto-Scaling #

Di lingkungan cloud dengan auto-scaling, weight bisa dikelola secara programatik:

# Script: tambahkan server baru dengan weight rendah dulu (ramp-up)
add_server_with_ramp_up() {
    local new_ip=$1
    local config="/etc/nginx/conf.d/upstream.conf"

    # Tambahkan dengan weight rendah (hati-hati, monitor dulu)
    echo "    server $new_ip:3000 weight=1;" >> $config
    nginx -s reload
    echo "Server $new_ip ditambahkan dengan weight=1 (5% traffic)"

    sleep 300  # Monitor 5 menit

    # Jika tidak ada alert, naikkan weight
    sed -i "s/$new_ip:3000 weight=1/$new_ip:3000 weight=3/" $config
    nginx -s reload
    echo "Weight dinaikkan ke 3 (20% traffic)"
}

# Script: keluarkan server dengan graceful drain
remove_server_gracefully() {
    local ip=$1
    local config="/etc/nginx/conf.d/upstream.conf"

    # Turunkan weight ke 0 dulu (drain traffic)
    sed -i "s/$ip:3000 weight=[0-9]*/$ip:3000 weight=1/" $config
    nginx -s reload
    echo "Weight diturunkan ke 1"

    sleep 60  # Tunggu request yang sedang berjalan selesai

    # Tandai sebagai down
    sed -i "s/$ip:3000 weight=1/$ip:3000 down/" $config
    nginx -s reload
    echo "Server $ip ditandai down, bisa di-terminate"
}

Tabel Rekomendasi Weight #

Beberapa rasio weight yang umum digunakan:

SkenarioRasioContoh
Server identik1:1:1weight=1 semua
Server 2x lebih kuat2:1weight=2, weight=1
Mix generasi hardware4:2:1weight=4, weight=2, weight=1
Canary 5%19:1weight=95, weight=5
Canary 10%9:1weight=9, weight=1
Canary 20%4:1weight=4, weight=1
Canary 50%1:1weight=1, weight=1

Automasi Weight Management dalam CI/CD #

Untuk tim yang melakukan deployment sering, weight management bisa diotomasi sebagai bagian dari pipeline CI/CD:

#!/bin/bash
# deploy-canary.sh: Deploy versi baru sebagai canary

NEW_SERVER=$1        # IP server baru dengan versi baru
INITIAL_WEIGHT=5     # Mulai dengan 5%
CONFIG="/etc/nginx/conf.d/upstream.conf"

# Step 1: Tambahkan server baru dengan weight rendah
cat >> $CONFIG << EOF
    server $NEW_SERVER:3000 weight=$INITIAL_WEIGHT;  # canary v2
EOF

nginx -t && nginx -s reload
echo "Canary deployed: $NEW_SERVER dengan weight=$INITIAL_WEIGHT"

# Step 2: Monitor selama 10 menit
echo "Monitoring error rate selama 10 menit..."
sleep 600

# Hitung error rate canary dari log
ERROR_RATE=$(awk -v server="$NEW_SERVER" '
    $5 ~ server && $6 >= 500 { err++ }
    $5 ~ server { total++ }
    END { if(total > 0) print int(err*100/total); else print 0 }
' /var/log/nginx/access.log)

echo "Error rate canary: ${ERROR_RATE}%"

if [ "$ERROR_RATE" -gt 5 ]; then
    echo "ERROR RATE TINGGI! Rollback canary..."
    # Tandai server sebagai down
    sed -i "s/$NEW_SERVER:3000 weight=$INITIAL_WEIGHT/$NEW_SERVER:3000 down/" $CONFIG
    nginx -t && nginx -s reload
    echo "Rollback selesai. Alert dikirim ke tim."
    exit 1
else
    echo "Error rate OK. Siap untuk full rollout."
    # Naikkan weight ke 50%
    sed -i "s/$NEW_SERVER:3000 weight=$INITIAL_WEIGHT/$NEW_SERVER:3000 weight=50/" $CONFIG
    nginx -t && nginx -s reload
fi
# GitHub Actions: deploy canary sebagai step dalam pipeline
jobs:
  deploy-canary:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy canary server
        run: |
          ssh deploy@nginx-server \
            'bash /usr/local/bin/deploy-canary.sh ${{ env.CANARY_IP }}'          

      - name: Monitor canary (10 menit)
        run: sleep 600

      - name: Promote to 100% jika sehat
        run: |
          ssh deploy@nginx-server \
            'sed -i "s/weight=50/weight=100/g" /etc/nginx/conf.d/upstream.conf && nginx -s reload'          

Pertimbangan Weight untuk Berbagai Workload #

# Workload I/O-bound (API, web server biasa)
# Distribusi berdasarkan RAM dan CPU lebih relevan
upstream io_bound {
    server web-1:3000 weight=4;   # 16 core, 32GB RAM
    server web-2:3000 weight=2;   # 8 core, 16GB RAM
    server web-3:3000 weight=1;   # 4 core, 8GB RAM
    keepalive 32;
}

# Workload CPU-bound (image processing, ML inference, video transcoding)
# CPU core count lebih relevan dari RAM
upstream cpu_bound {
    server gpu-1:8000 weight=8;   # 8 GPU A100
    server gpu-2:8000 weight=4;   # 4 GPU A100
    server cpu-1:8001 weight=1;   # CPU saja, fallback
    keepalive 8;
}

# Microservices dengan SLA berbeda
# Server di region terdekat mendapat weight lebih tinggi
upstream geo_aware {
    # Server Asia Tenggara (dekat dengan user Indonesia)
    server sg-1:3000 weight=10;   # Singapore
    server sg-2:3000 weight=10;   # Singapore
    # Server Asia Timur (latensi lebih tinggi)
    server jp-1:3000 weight=3;    # Japan
    keepalive 16;
}

Verifikasi Distribusi Weight #

Setelah mengkonfigurasi weight, penting untuk memverifikasi bahwa distribusi traffic berjalan sesuai yang diharapkan:

# Cek distribusi traffic dari access log
# Format log harus mencakup $upstream_addr
awk '{print $5}' /var/log/nginx/access.log | \
    sort | uniq -c | sort -rn

# Output contoh (weight=4, weight=2, weight=1):
# 4021 10.0.0.1:3000   ← ~57% (ekspektasi: 4/7 = 57.1%)
# 2009 10.0.0.2:3000   ← ~29% (ekspektasi: 2/7 = 28.6%)
#  978 10.0.0.3:3000   ← ~14% (ekspektasi: 1/7 = 14.3%)
# Total: 7008 request → Distribusi sangat akurat!

# Jika distribusi tidak sesuai, kemungkinan:
# 1. Server ditandai max_fails (tidak masuk rotasi sementara)
# 2. max_conns tercapai di salah satu server
# 3. Tidak menggunakan zone directive (data tidak sinkron antar worker)
# Verifikasi weight yang aktif
nginx -T | grep -A 10 "upstream app_servers"
# Atau tampilkan konfigurasi yang sedang berjalan:
nginx -T 2>/dev/null | grep -E "server.*weight"

Formula Menghitung Persentase Traffic #

Diketahui: server A weight=5, server B weight=3, server C weight=2
Total weight = 5 + 3 + 2 = 10

Persentase Server A = 5/10 × 100 = 50%
Persentase Server B = 3/10 × 100 = 30%
Persentase Server C = 2/10 × 100 = 20%

Jika traffic = 10.000 req/menit:
  Server A mendapat: 5.000 req/menit
  Server B mendapat: 3.000 req/menit
  Server C mendapat: 2.000 req/menit

Implikasi Weight terhadap High Availability #

Satu hal yang sering diabaikan: weight mempengaruhi perilaku failover. Jika server dengan weight tinggi down, dampaknya lebih besar terhadap kapasitas keseluruhan:

Setup: Server A weight=8, Server B weight=2
Kapasitas normal: A menangani 80%, B menangani 20%

Jika Server A down:
  Semua traffic masuk ke Server B
  Server B yang biasa hanya menangani 20% sekarang harus menangani 100%
  Server B kemungkinan besar tidak sanggup → overload!

Setup yang lebih aman untuk HA:
  Server A weight=3, Server B weight=2, Server C weight=1
  Total 6 bagian
  Jika A down: B mendapat 2/3 = 67%, C mendapat 1/3 = 33%
    → Masih mungkin tertangani jika B dan C cukup kuat
# Konfigurasi yang mempertimbangkan kapasitas failover:
upstream production {
    # Server utama: bisa menangani 100% traffic sendiri jika darurat
    server 10.0.0.1:3000 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:3000 weight=3 max_fails=3 fail_timeout=30s;
    # Server bantu: lebih kecil, tapi bisa cover jika satu server utama down
    server 10.0.0.3:3000 weight=1 max_fails=3 fail_timeout=30s;
    # Backup: hanya jika semua server di atas down
    server 10.0.0.4:8080 backup;

    keepalive 32;
    zone prod_upstream 128k;
}
# Normal: A=3/7=43%, B=3/7=43%, C=1/7=14%
# Jika A down: B=3/4=75%, C=1/4=25% (masih reasonable)
# Jika A dan B down: C=100% (overload, tapi backup server akan aktif)

Checklist Sebelum Menggunakan Weight di Production #

Sebelum menerapkan konfigurasi weight di production, pastikan semua poin berikut sudah terpenuhi:

☐ Weight sudah dihitung berdasarkan kapasitas aktual server
  (CPU core, RAM, bandwidth, benchmark hasil load test)

☐ Server dengan weight paling tinggi mampu menangani setidaknya 60%
  traffic sendirian (antisipasi jika server lain down)

☐ Ada setidaknya satu server backup atau konfigurasi graceful degradation

☐ Format log sudah mencakup $upstream_addr untuk memverifikasi distribusi

☐ Sudah ada monitoring aktif yang mendeteksi jika satu server menerima
  traffic jauh lebih banyak dari yang diharapkan

☐ Jika ini adalah canary deployment: sudah ada script atau prosedur rollback
  yang bisa dieksekusi dalam < 2 menit

☐ Konfigurasi sudah di-test di staging dengan load test yang mencerminkan
  traffic production

☐ Tim sudah tahu cara mengubah weight dan reload Nginx tanpa downtime

Ringkasan #

  • weight=N mengontrol proporsi traffic secara relatif — server dengan weight=3 mendapat 3x lebih banyak request dari server dengan weight=1.
  • Berguna untuk server dengan kapasitas berbeda agar distribusi beban sesuai kemampuan masing-masing.
  • Canary deployment: mulai dengan weight kecil untuk versi baru (misalnya weight=5 dari total weight=100), monitor error rate, naikkan secara bertahap.
  • Blue-green deployment: gunakan weight=0 backup untuk versi standby, switch dengan ubah konfigurasi dan nginx -s reload.
  • Bisa dikombinasikan dengan least_conn — formula efektif = koneksi_aktif / weight, server berkapasitas besar butuh lebih banyak koneksi sebelum dianggap sibuk.
  • Perubahan weight bisa dilakukan tanpa downtime dengan nginx -s reload — koneksi yang sedang berjalan tidak terputus.

← Sebelumnya: IP Hash   Berikutnya: Health Check →

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