Round-robin mendistribusikan permintaan secara bergiliran, yang bekerja baik untuk panggilan API stateless berumur pendek. Untuk koneksi WebSocket atau sesi yang berumur panjang, least_conn lebih tepat karena ia merutekan setiap koneksi baru ke server dengan koneksi aktif paling sedikit, mencegah satu backend menumpuk beban yang tidak proporsional sementara server lain menganggur.
Passive health check Nginx menandai backend sebagai tidak tersedia berdasarkan kegagalan yang diamati, bukan dengan probing aktif. Parameter max_fails mengatur berapa banyak kegagalan berturut-turut yang memicu status tidak tersedia, dan fail_timeout mengatur berapa lama server keluar dari pool sebelum dicoba kembali. Titik awal produksi yang praktis adalah max_fails=3 fail_timeout=30s — tiga kegagalan berturut-turut menarik server selama 30 detik, setelah itu satu permintaan uji menentukan apakah server bergabung kembali ke pool.
Selalu jalankan nginx -t terlebih dahulu untuk memvalidasi sintaks konfigurasi sebelum menerapkan perubahan — file konfigurasi yang buruk menyebabkan reload gagal dengan aman sementara konfigurasi lama tetap aktif. Kemudian gunakan nginx -s reload, yang memunculkan worker process baru dengan konfigurasi terbaru sementara koneksi aktif selesai secara normal pada worker lama. Uji perubahan di staging terlebih dahulu, dan pertimbangkan pendekatan canary dengan menerapkan perubahan ke satu load balancer dalam cluster sebelum semua.
Mengakhiri SSL di load balancer Nginx memusatkan manajemen sertifikat ke satu titik, mengurangi beban CPU pada server backend karena TLS handshake sangat intensif CPU, dan menyederhanakan konfigurasi backend karena server tersebut hanya menangani HTTP biasa di jaringan internal. Certbot dengan plugin Nginx dapat mendapatkan dan memperbarui otomatis sertifikat Let's Encrypt langsung pada load balancer.
Nginx adalah pilihan tepat pada volume traffic sedang (ribuan permintaan per menit) karena familiar, berfungsi ganda sebagai load balancer dan web server, serta gratis. HAProxy menawarkan kemampuan health check yang lebih kuat, termasuk active health check dalam edisi open source-nya, dan layak dipertimbangkan pada volume traffic lebih tinggi atau ketika load balancing UDP dibutuhkan. Opsi cloud seperti GCP Cloud Load Balancing atau Cloudflare sangat baik untuk distribusi traffic global dengan failover lintas region, tetapi menambahkan biaya dan kompleksitas operasional yang sulit dijustifikasi untuk beban kerja regional seperti klien UKM Indonesia yang berjalan di region Singapura.
Saat pertama kali saya men-deploy setup multi-server untuk klien di Commsult Indonesia, konfigurasi load balancer sangat naif: round-robin ke tiga upstream server tanpa health check, tanpa batas koneksi, dan tanpa penyetelan timeout. Pertama kali satu server backend kehabisan memori dan mulai mengembalikan 504, Nginx dengan setia terus mengirim 33% traffic ke sana selama beberapa menit sebelum monitoring memberi tahu kami. Load balancer produksi memerlukan logika health check aktif, failover yang anggun, dan konfigurasi upstream yang tepat. Panduan ini mencakup apa yang telah saya pelajari dalam memelihara Nginx sebagai load balancer untuk web API yang melayani klien berbasis Jakarta.
Blok upstream di Nginx mendefinisikan kumpulan server backend dan cara traffic didistribusikan di antara mereka. Algoritma default adalah round-robin — setiap permintaan dikirim ke server berikutnya dalam daftar secara bergiliran. Untuk API stateless (REST, GraphQL), round-robin bekerja dengan baik. Untuk koneksi WebSocket atau sesi yang berumur panjang, least_conn lebih baik — ini merutekan setiap koneksi baru ke server dengan koneksi aktif paling sedikit, mencegah akumulasi koneksi pada satu server. Direktif ip_hash tersedia untuk sesi sticky tetapi harus dihindari dalam arsitektur modern di mana state sesi ada di Redis, bukan di memori pada server tertentu.
Server upstream Nginx mendukung parameter weight untuk mengalihkan lebih banyak atau lebih sedikit traffic ke server tertentu. Jika satu backend memiliki CPU dan RAM dua kali lipat, atur weight=2 untuk mengirimnya dua kali lipat traffic. Parameter backup menandai server sebagai failover — hanya menerima traffic ketika semua server utama tidak tersedia. Ini berguna untuk degradasi yang anggun: server backup yang menjalankan versi aplikasi yang disederhanakan menangani traffic ketika armada utama down, mengembalikan sesuatu yang berguna daripada error 502. Dalam setup kami, kami memiliki satu Droplet yang dikonfigurasi sebagai backup yang menyajikan halaman maintenance ketika dua server utama keduanya tidak tersedia.
Timeout default Nginx terlalu lama untuk sebagian besar API produksi. proxy_connect_timeout mengontrol berapa lama Nginx menunggu koneksi ke backend — 60 detik adalah default, yang tidak masuk akal untuk koneksi jaringan lokal. Atur ini ke 5-10 detik. proxy_read_timeout mengontrol berapa lama Nginx menunggu backend mengirim respons setelah koneksi terjalin — default 60 detik, yang berarti Nginx menahan koneksi terbuka selama satu menit pada backend yang macet. Setel ini agar sesuai dengan waktu pemrosesan permintaan aktual Anda ditambah margin keamanan. proxy_send_timeout mengontrol berapa lama Nginx menunggu saat mengirim permintaan ke backend.
Dari pengalaman saya: atur proxy_next_upstream error timeout http_500 http_502 http_503 dan proxy_next_upstream_tries 2 di blok lokasi upstream Anda. Ini memberi tahu Nginx untuk secara otomatis mencoba ulang permintaan yang gagal pada upstream server berikutnya untuk error server dan timeout. Dikombinasikan dengan health check yang tepat, ini memberikan failover otomatis untuk error backend transien tanpa memengaruhi pengguna akhir. Saya pernah mengalami kasus di mana proses Node.js crash di tengah permintaan dan pengguna tidak menyadarinya karena Nginx mencoba ulang pada backend yang sehat dalam milidetik.
Nginx open-source mendukung passive health check — ia menandai backend sebagai tidak tersedia berdasarkan kegagalan yang diamati. Parameter max_fails mengatur berapa banyak kegagalan berturut-turut yang menyebabkan server ditandai sebagai tidak tersedia. Parameter fail_timeout mengatur berapa lama server tetap tidak tersedia sebelum Nginx mencoba kembali. Titik awal produksi: max_fails=3 fail_timeout=30s. Ini berarti tiga kegagalan berturut-turut (timeout atau kesalahan koneksi) menandai server tidak tersedia selama 30 detik, setelah itu Nginx mencoba satu permintaan untuk menguji apakah telah pulih. Jika permintaan tersebut berhasil, server dikembalikan ke pool; jika gagal, timeout 30 detik diatur ulang.
# /etc/nginx/conf.d/upstream.conf
upstream api_backend {
least_conn;
server 10.0.1.10:3000 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.1.11:3000 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.1.12:3000 backup; # failover server
}
# Rate limiting zone
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://api_backend;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 10s;
proxy_next_upstream error timeout http_500 http_502 http_503;
proxy_next_upstream_tries 2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Akhiri SSL di load balancer Nginx dan teruskan HTTP ke server backend di jaringan internal. Ini memusatkan manajemen sertifikat, mengurangi beban CPU pada server backend (TLS handshake intensif CPU), dan menyederhanakan konfigurasi backend. Gunakan Certbot dengan plugin Nginx untuk mendapatkan dan memperbarui otomatis sertifikat Let's Encrypt pada load balancer. Lewatkan header X-Forwarded-For, X-Forwarded-Proto, dan X-Real-IP dari load balancer ke backend sehingga kode aplikasi dapat membaca IP dan protokol klien yang sebenarnya. Selalu verifikasi bahwa aplikasi Anda menggunakan header ini dengan benar — mencatat IP yang salah atau mempercayai HTTP ketika HTTPS diperlukan dapat menyebabkan masalah nyata.
┌─────────────────────────────────────────────────────┐
│ Nginx Load Balancer Production Setup │
├─────────────────────────────────────────────────────┤
│ │
│ Internet → Cloudflare CDN │
│ ↓ │
│ Nginx Load Balancer (443 SSL) │
│ [rate limiting, SSL termination] │
│ ↓ ↓ │
│ Backend 1:3000 Backend 2:3000 │
│ (weight=2) (weight=2) │
│ ↑ │
│ Backup :3000 (if both fail) │
│ │
│ Health: max_fails=3 fail_timeout=30s │
└─────────────────────────────────────────────────────┘Saya pernah memodifikasi konfigurasi upstream Nginx pada load balancer produksi untuk mengubah algoritma load balancing dari round-robin ke least_conn. Saya mengedit nginx.conf dan menjalankan nginx -s reload — yang saya harapkan akan diterapkan dengan anggun. Yang saya lewatkan: saya secara tidak sengaja menghapus salah satu entri upstream server, sehingga reload langsung mengurangi sepertiga kapasitas backend. Perintah nginx -s reload menerapkan perubahan pada koneksi baru tetapi tidak memvalidasi bahwa upstream server dapat dijangkau. Selalu jalankan nginx -t terlebih dahulu (tes konfigurasi), selalu uji perubahan pada staging, dan pertimbangkan pendekatan canary di mana Anda menerapkan perubahan ke satu PoP atau satu load balancer dalam cluster sebelum semua.
Load balancer tanpa rate limiting rentan terhadap lonjakan traffic yang membanjiri backend. Direktif limit_req_zone dan limit_req Nginx mengimplementasikan token-bucket rate limiting per IP. Konfigurasi umum: 10 permintaan per detik per IP untuk API dengan allowance burst 20. Klien dalam batas burst dilayani segera; klien yang melebihi rate limit menerima 429 Too Many Requests. Untuk API terautentikasi di mana rate limiting per pengguna lebih tepat daripada per IP, gunakan zone key berbasis header: $http_x_user_id. Kombinasikan dengan fail2ban pada backend untuk memblokir IP yang berulang kali memicu rate limit.
Nginx mendukung zero-downtime reload konfigurasi melalui nginx -s reload. Proses master membaca konfigurasi baru, memunculkan worker process baru dengan konfigurasi yang diperbarui, dan menguras koneksi yang ada pada worker lama dengan anggun. Koneksi aktif selesai secara normal; koneksi baru pergi ke worker baru. Ini berarti Anda dapat memperbarui daftar upstream server, mengubah nilai timeout, atau memodifikasi sertifikat SSL tanpa menjatuhkan satu koneksi pun. Prasyarat kritis: selalu jalankan nginx -t sebelum nginx -s reload untuk memvalidasi sintaks konfigurasi. File konfigurasi yang buruk menyebabkan reload gagal dengan konfigurasi lama yang tetap aktif — yang sebenarnya merupakan perilaku aman.
Untuk skala yang saya jalankan di Commsult Indonesia (ribuan permintaan per menit, bukan jutaan), Nginx adalah pilihan yang tepat: familiar, terdokumentasi dengan baik, berfungsi ganda sebagai load balancer dan web server, dan gratis. HAProxy memiliki kemampuan health check yang lebih kuat (termasuk active health check dalam open source) dan dibangun khusus untuk load balancing dengan set fitur yang lebih kaya — layak dipertimbangkan untuk volume traffic lebih tinggi atau ketika Anda memerlukan load balancing UDP. Cloud Load Balancing GCP dan load balancing Cloudflare sangat baik untuk distribusi traffic global dengan failover otomatis lintas region, tetapi menambahkan biaya dan kompleksitas operasional yang tidak dibenarkan untuk workload klien UKM Indonesia yang berjalan di region Singapura.
Sumber & Bacaan Lanjutan