Batasi overload
Admission control, rate limit, bulkhead, circuit breaker, backpressure, dan degradasi terkontrol: apa masing-masing lindungi, dan kapan salah dipakai.
Pertanyaan
Saat beban melebihi kapasitas, apa yang sengaja kita tolak atau turunkan supaya sisanya tetap jalan?
Setelah baca ini, kamu bisa milih mekanisme perlindungan yang pas buat satu gejala overload, dan ngitung kapan antrean tanpa batas berubah jadi kegagalan massal.
Prasyarat dan contoh
Kamu sudah paham hubungan beban, antrean, dan latensi (M01 dan M02), serta kenapa retry bisa melipatgandakan trafik (M03). Lesson ini nyambung ke SLI latensi dan ketersediaan di M16.01.
Contoh: API pesanan dirancang buat 400 request/detik, tiap request butuh rata-rata 20 ms CPU di 8 worker, jadi kapasitas jenuh sekitar 8 / 0,02 = 400 request/detik. Kampanye datang dan trafik mencapai 600 request/detik. Antrean tumbuh 200 request/detik. Dalam 30 detik ada 6.000 request menunggu, yang di titik itu butuh 15 detik cuma buat antre. Klien timeout di 5 detik dan retry, jadi trafik efektif naik lagi, padahal hasil kerja server mayoritas dibuang karena kliennya sudah pergi.
Mekanisme
Prinsip dasarnya: lebih baik menolak sebagian dengan cepat daripada melayani semua dengan lambat dan gagal. Antrean yang tumbuh tanpa batas cuma menunda kegagalan dan menambah latensi.
Admission control menolak pekerjaan di pintu masuk saat sistem sudah penuh. Bentuk sederhana:
batas concurrency (maksimum 64 request in-flight, sisanya 503 dengan Retry-After). Berdasar
Little's law, in-flight ≈ laju × latensi, jadi batas in-flight juga membatasi latensi. Bisa
ditambah prioritas: bayar dan login lolos duluan, pencarian ditolak duluan.
Rate limit membatasi laju per pemanggil (per API key atau IP) supaya satu klien nggak memakan jatah semua. Algoritma umum: token bucket (isi 50 token/detik, kapasitas 100 buat burst). Rate limit melindungi dari kenakalan atau kesalahan satu klien, bukan dari lonjakan kolektif banyak klien yang sah. Itu tugas admission control.
Bulkhead memisahkan sumber daya per kelompok supaya kegagalan satu nggak menenggelamkan semuanya. Contoh: pool koneksi database terpisah, 20 buat jalur pembayaran dan 10 buat laporan. Laporan yang lambat menghabiskan jatahnya sendiri, bukan jatah pembayaran.
Circuit breaker berhenti memanggil dependensi yang jelas sedang gagal. Tiga keadaan: tertutup (normal), terbuka (langsung gagal atau pakai fallback, misalnya setelah 50% gagal dari minimal 20 panggilan dalam 10 detik), dan setengah terbuka (coba sedikit panggilan buat cek pulih). Gunanya melindungi pemanggil dari antre dan menghabiskan thread, sekaligus memberi napas bagi dependensi.
Backpressure meneruskan sinyal "pelan-pelan" ke hulu. Antrean berbatas yang penuh memblokir atau menolak produser, bukan membesar tanpa batas. Di stream, ini berarti konsumen menarik data sesuai kapasitasnya (credit-based) dan produser berhenti saat kreditnya habis.
Degradasi terkontrol mengganti jawaban penuh dengan yang lebih murah: matikan rekomendasi personal dan tampilkan daftar populer yang di-cache, tunda pembuatan thumbnail, turunkan resolusi. Keputusannya harus dirancang sebelum insiden, lengkap dengan saklar dan metrik yang menandai bahwa mode degradasi aktif.
Saat rancangan ini gagal
- Antrean tanpa batas. Latensi naik tanpa batas dan memori habis. Server tetap "sehat" di health check sambil nggak memberi hasil berguna.
- Rate limit sebagai satu-satunya pertahanan. Seribu klien sah, masing-masing di bawah limit, tetap bisa menjenuhkan sistem. Butuh admission control global.
- Circuit breaker salah ambang. Terlalu sensitif: buka karena beberapa error acak lalu memutus dependensi yang sebenarnya sehat. Terlalu longgar: terlambat melindungi.
- Limit yang dihitung per instance. 10 instance dengan limit lokal 100/detik berarti 1.000 total, bukan 100. Limit terdistribusi butuh penyimpanan bersama dan menambah dependensi baru yang bisa gagal sendiri. Putuskan fail-open atau fail-closed.
- Degradasi yang nggak pernah diuji. Mode fallback yang baru dijalankan saat insiden sering rusak karena cache dingin atau konfigurasi usang.
- Bulkhead terlalu kecil atau terlalu banyak. Kapasitas menganggur di satu kolam sementara kolam lain kehabisan.
Contoh tandingan: breaker di depan layanan stok membuka dan mengembalikan "stok tersedia" dari cache. Cocok buat katalog, berbahaya buat checkout, karena menjual barang yang sudah habis. Fallback harus sesuai konsekuensi bisnis per alur.
Latihan
Layanan di contoh di atas: kapasitas 400 request/detik, 8 worker, rata-rata 20 ms per request. Trafik 600 request/detik datang tiba-tiba. Klien timeout 5 detik dan retry sekali.
- Dengan batas in-flight 40, berapa latensi maksimum kira-kira dalam kondisi jenuh, dan berapa request/detik yang ditolak?
- Kenapa batas in-flight 40 lebih baik daripada antrean 6.000?
- Jalur mana yang kamu lindungi duluan kalau harus memilih, dan gimana kamu menerapkannya?
Lihat pembahasan
- In-flight ≈ laju × latensi, jadi latensi ≈ 40 / 400 = 0,1 detik (100 ms) saat jenuh. Yang diterima 400 request/detik, jadi sekitar 200 request/detik ditolak (600 - 400).
- Antrean 6.000 pada 400 request/detik berarti tunggu 15 detik, jauh di atas timeout klien 5 detik. Server mengerjakan request yang hasilnya dibuang dan klien retry, jadi beban efektif naik. Dengan batas 40, request yang diterima selesai dalam sekitar 100 ms, dan yang ditolak gagal cepat sehingga klien bisa memutuskan retry dengan backoff.
- Lindungi pembayaran dan login. Terapkan antrean atau batas in-flight terpisah per kelas
(bulkhead logis), mis. 30 slot buat pembayaran dan 10 buat pencarian, atau tolak dulu kelas
prioritas rendah saat in-flight penuh. Pastikan penolakan memberi 503 dengan
Retry-After, dan pantau persentase ditolak per kelas sebagai bagian dari SLI.
Perhatikan hasilnya: server menolak 33% trafik, tapi 67% sisanya sukses dengan cepat. Tanpa batas, kemungkinan hampir semuanya gagal.
Terkait
- M16.01 Ukur perjalanan pengguna memberi SLI buat memutuskan kapan menolak dan menandai mode degradasi.
- M01.03 Perkirakan kebutuhan sumber daya menghitung kapasitas yang jadi batas atas di sini.
- M16.06 Tangani insiden dan tinjau rancangan memakai saklar degradasi saat insiden.
Catatan
- Asumsi: layanan CPU-bound, waktu layanan tetap 20 ms, dan Little's law berlaku pada kondisi stabil.
- Ambang circuit breaker adalah contoh, bukan nilai universal. Kalibrasi dengan data sendiri.
- Yang nggak dibahas: algoritma rate limit terdistribusi, adaptive concurrency limit, dan load shedding berbasis deadline di service mesh.
- Terakhir ditinjau: 26 Oktober 2026.