Kodeloka
  1. Kodeloka
  2. Kelas Nginx
  3. Materi

2 · Reverse Proxy · Modul 4 dari 8

Upstream & Penyeimbang Beban

Membagi beban ke beberapa server hulu, dan menyingkirkan yang bermasalah tanpa menjatuhkan permintaan.

Blok upstream

upstream backend {
    server 10.0.1.10:3000  weight=3;
    server 10.0.1.11:3000  weight=1;
    server 10.0.1.12:3000  backup;

    keepalive 32;
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

Metode Pembagian Beban

upstream backend {
    # round robin — bawaan, tanpa perlu ditulis
    server a:3000;
    server b:3000;
}

upstream backend {
    least_conn;              # ke server dengan koneksi aktif paling sedikit
    server a:3000;
}

upstream backend {
    ip_hash;                 # klien yang sama selalu ke server yang sama
    server a:3000;
}

upstream backend {
    hash $request_uri consistent;   # berdasarkan URI, cocok untuk cache
    server a:3000;
}

least_conn biasanya pilihan paling aman ketika durasi permintaan bervariasi — round robin membagi rata jumlah permintaan, bukan beban sesungguhnya, sehingga satu server bisa menumpuk permintaan berat sementara yang lain menganggur.

⚠️ ip_hash bukan pengganti sesi bersama

ip_hash sering dipakai agar sesi login tetap menempel di satu server. Masalahnya: menambah atau menghapus satu server mengubah pemetaan untuk sebagian besar klien sehingga sesi hilang serentak. Klien di belakang NAT perusahaan juga menumpuk ke satu server yang sama. Menyimpan sesi di Redis jauh lebih tahan banting.

keepalive: Penyetelan Kecil, Dampak Besar

Tanpa keepalive, Nginx membuka koneksi TCP baru ke hulu untuk setiap permintaan lalu menutupnya. Pada lalu lintas tinggi, biaya jabat tangan TCP dan port yang menumpuk di keadaan TIME_WAIT menjadi hambatan nyata.

🚫 keepalive tidak bekerja tanpa dua baris pendamping

Menulis keepalive 32 saja tidak cukup. Nginx berbicara HTTP/1.0 ke hulu secara bawaan dan tetap mengirim header Connection: close. Dua direktif ini wajib menyertainya:

proxy_http_version 1.1;
proxy_set_header Connection "";

Tanpa keduanya, angka keepalive tidak berpengaruh sama sekali dan koneksi tetap dibuat-tutup setiap permintaan.

Menyingkirkan Server Bermasalah

upstream backend {
    server 10.0.1.10:3000 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:3000 max_fails=3 fail_timeout=30s;
}

Ini pemeriksaan pasif: setelah 3 kegagalan dalam rentang 30 detik, server ditandai tidak sehat dan dilewati selama 30 detik berikutnya, lalu dicoba lagi. Nginx sumber terbuka tidak memiliki pemeriksaan aktif — fitur itu hanya ada pada Nginx Plus atau modul pihak ketiga.

Mengulang ke Server Lain

proxy_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries   2;
proxy_next_upstream_timeout 10s;
🚫 Jangan pernah menambahkan non_idempotent tanpa berpikir panjang

Secara bawaan Nginx tidak mengulang permintaan POST, PATCH, atau LOCK ke server lain — dan itu disengaja. Bila hulu sudah menerima serta memproses POST /pembayaran lalu gagal saat mengirim balasan, mengulangnya ke server lain berarti pembayaran diproses dua kali. Menambahkan non_idempotent hanya aman bila endpoint benar-benar melindungi diri dengan kunci idempoten.

Resolusi DNS yang Berubah

resolver 10.0.0.2 valid=30s ipv6=off;

location / {
    set $hulu "layanan.internal:3000";
    proxy_pass http://$hulu;
}
💡 Nginx menahan hasil DNS selamanya bila host ditulis langsung

Nama host di dalam proxy_pass diselesaikan sekali saat startup dan tidak pernah diperiksa lagi. Di Kubernetes atau lingkungan dengan IP yang berpindah, Nginx akan terus mengirim ke alamat yang sudah mati sampai di-reload. Memakai variabel memaksa Nginx menyelesaikan DNS saat permintaan datang, mengikuti valid= pada resolver.