Pertanyaan dan Kapan Pertanyaan Ini Berlaku
Sebuah layanan pesanan memiliki kapasitas berkelanjutan yang telah diuji beban sebesar 3.000 permintaan per detik pada latensi p99 sebesar 250 ms. Selama masa promosi, kedatangan trafik melonjak menjadi 8.000 permintaan per detik. Dependensi inventaris melambat, jumlah permintaan yang sedang berjalan (in-flight) dan usia antrean sama-sama meningkat, klien melakukan percobaan ulang, dan autoscaling memerlukan waktu tiga menit sebelum instans baru siap. Pengiriman pesanan penting, pemeriksaan ketersediaan interaktif, dan rekonsiliasi batch internal menggunakan layanan ini secara bersamaan.
Rancang kebijakan perlindungan kelebihan beban yang menjaga proses tetap responsif dan mempertahankan sebanyak mungkin pekerjaan yang berguna. Jelaskan sinyal deteksi, batasan konkurensi dan antrean, kontrol penerimaan (admission control), prioritas permintaan, degradasi halus, perilaku percobaan ulang, pemulihan, dan validasi. Angka-angka ini merupakan asumsi wawancara, bukan klaim tentang sistem produksi tertentu.
Ini adalah pertanyaan backend karena keputusan intinya adalah bagaimana satu layanan melindungi CPU, memori, thread, koneksi, dan panggilan ke layanan hilir (downstream). Rate limiter terdistribusi menerapkan kebijakan trafik di seluruh tenant atau jendela waktu; pertanyaan ini dimulai setelah trafik yang diizinkan masih lebih besar daripada kapasitas layanan saat itu. Batas waktu (timeout), percobaan ulang, dan circuit breaker melindungi panggilan dependensi individu, sedangkan kontrol kelebihan beban memutuskan pekerjaan baru mana yang mampu diterima oleh layanan.
Apa yang Sedang Dievaluasi oleh Pewawancara
Jawaban yang kuat mengidentifikasi saturasi dari beban kerja lokal, bukan hanya dari tingkat permintaan semata. Ambang batas permintaan per detik yang tetap akan gagal ketika satu permintaan menjadi lima kali lebih berat atau ketika perlambatan dependensi menahan koneksi lebih lama. Pekerjaan yang sedang berjalan, usia antrean, slot worker atau koneksi yang tersedia, CPU, tekanan memori, dan sisa batas waktu (deadline slack) menunjukkan sumber daya mana yang sebenarnya sedang menipis.
Sinyal berikutnya adalah sistem yang berbatas (bounded). Antrean tanpa batas mengubah permintaan berlebih menjadi pembengkakan memori dan penumpukan permintaan usang. Seorang kandidat harus membatasi pekerjaan konkuren pada titik hambatan (bottleneck), menjaga antrean tetap kecil atau meniadakannya, dan menolak dengan biaya komputasi rendah sebelum parsing yang berat atau panggilan downstream dilakukan. Tujuannya adalah pekerjaan sukses yang berguna, bukan menerima setiap permintaan atau memaksimalkan jumlah percobaan mentah.
Pewawancara juga menginginkan kebijakan yang memahami konteks bisnis. Pengiriman pesanan penting dapat menerima porsi alokasi khusus; pemeriksaan ketersediaan dapat menggunakan cache berumur pendek; rekonsiliasi batch dapat dijeda. Prioritas tetap memerlukan keadilan per-tenant sehingga satu pelanggan besar tidak dapat menghabiskan setiap slot yang dialokasikan. Terakhir, desain tersebut memerlukan loop pemulihan tertutup: menekan amplifikasi percobaan ulang, melakukan penskalaan sebagai respons kapasitas yang lebih lambat, menaikkan tingkat penerimaan kembali secara bertahap, dan menguji jalur degradasi sebelum terjadi insiden.
Pertanyaan untuk Diklarifikasi Sebelum Menjawab
- Sumber daya apa yang mengalami saturasi terlebih dahulu? Saturasi CPU lebih cocok ditangani dengan batas konkurensi atau biaya lokal. Dependensi yang lambat memerlukan bulkhead koneksi/konkurensi terpisah. Pembengkakan memori atau usia antrean mungkin memerlukan antrean yang lebih kecil dan penolakan yang lebih awal. Setiap bottleneck mengubah sinyal kontrol penerimaan.
- Operasi mana yang esensial dan apa yang dapat didegradasi? Di sini, pengiriman pesanan bersifat kritis, ketersediaan dapat mentoleransi data yang sedikit usang, dan rekonsiliasi batch dapat dijeda. Jika setiap operasi secara hukum diwajibkan menggunakan inventaris terbaru, fallback cache tidak valid dan kegagalan eksplisit lebih aman.
- Berapa batas waktu menyeluruh (end-to-end deadline)? Waktu dalam antrean menghabiskan batas waktu yang sama dengan waktu eksekusi. Layanan harus membuang pekerjaan yang tidak lagi dapat diselesaikan dan menyebarkan pembatalan ke layanan downstream.
- Apakah biaya pemrosesan setiap permintaan sama beratnya? Satu token per permintaan hanya berfungsi jika biayanya serupa. Endpoint yang berat mungkin memerlukan izin berbobot (weighted permits) atau kumpulan pool terpisah sehingga pekerjaan kritis yang ringan tidak terjebak di belakang tugas batch yang memakan banyak sumber daya.
- Bisakah klien mencoba ulang dengan aman? Operasi baca yang ditolak dapat dicoba lagi nanti. Operasi tulis pesanan memerlukan kunci idempoten (idempotency key) dan pencarian hasil. Layanan harus membedakan antara "coba lagi nanti" dan "jangan coba lagi", serta semua lapisan harus berbagi anggaran percobaan ulang (retry budget).
- Apakah pengalihan trafik tersedia? Failover ke wilayah yang sehat hanya dapat menyerap beban jika target memiliki kapasitas cadangan yang terverifikasi. Memindahkan kelebihan beban secara membabi buta dapat menciptakan kegagalan kedua.
Kerangka Jawaban 30 Detik
"Saya akan melindungi titik hambatan dengan sebuah closed loop kecil. Pertama, gunakan uji beban untuk menetapkan batas konkurensi dan antrean per instans, lalu pantau pekerjaan lokal yang sedang berjalan, usia antrean, CPU, memori, connection pool, dan sisa batas waktu. Ketika saturasi meningkat, tolak pekerjaan baru sebelum pemrosesan yang berat, cadangkan kapasitas untuk pengiriman pesanan, pertahankan keadilan dalam setiap prioritas, sajikan respons cache yang disetujui untuk ketersediaan, dan jeda pekerjaan batch. Penolakan menggunakan respons kelebihan beban sementara yang jelas, sementara klien hanya mencoba ulang operasi idempoten dengan backoff, jitter, dan anggaran percobaan ulang bersama. Autoscaling menambah kapasitas tetapi terlalu lambat untuk menjadi pertahanan pertama. Saya akan memulihkannya dengan histeresis dan peningkatan penerimaan bertahap, lalu memverifikasi memori yang berbatas, throughput berguna, keberhasilan operasi kritis, keadilan, amplifikasi percobaan ulang, dan pemulihan dalam uji kelebihan beban."
Pembahasan Mendalam Langkah demi Langkah
Mulailah dengan batas kapasitas yang terukur. Angka 3.000 permintaan per detik hanya valid untuk kombinasi permintaan yang diuji, latensi dependensi, jumlah instans, dan target p99 250 ms. Catat pekerjaan per instans yang sedang berjalan, CPU, memori, utilisasi worker, dan penggunaan koneksi downstream yang sesuai. Tingkat permintaan hanyalah input; keputusan penerimaan harus mengikuti sumber daya yang paling mendekati kegagalan. Misalnya, ketika inventaris melambat, laju kedatangan yang sama menghasilkan lebih banyak panggilan yang berjalan, sehingga pengontrol berbasis laju saja akan bereaksi terlambat.
Tempatkan batas konkurensi independen di sekitar sumber daya yang langka. Penangan pesanan memerlukan batas keseluruhan, sementara panggilan inventaris dan tugas batch mendapatkan bulkhead yang lebih kecil. Izin diperoleh sebelum mengalokasikan pekerjaan yang memakan sumber daya dan dilepaskan saat berhasil, gagal, waktu habis, atau dibatalkan. Jika biaya permintaan berbeda secara material, gunakan izin berbobot atau pool endpoint terpisah. Batas hard-code adalah titik awal yang aman dari uji beban; batas adaptif dapat meningkatkan utilisasi, tetapi memerlukan umpan balik yang stabil, guardrail, dan rollback cepat.
Jaga agar antrean bersifat eksplisit dan berbatas. Antrean pendek dapat menyerap lonjakan sesaat yang sudah diketahui, tetapi batasnya harus berasal dari sisa batas waktu daripada memori yang tersedia. Tolak saat antrean penuh atau saat perkiraan penundaan antrean menyisakan terlalu sedikit waktu untuk selesai. Antrean tanpa batas tidak dapat menciptakan kapasitas; hal itu meningkatkan tail latency, menahan memori, dan membuat klien mencoba ulang permintaan yang sebenarnya sudah menunggu. Pantau kedalaman antrean dan usia item tertua karena antrean kecil dari pekerjaan yang berat tetap bisa menjadi usang.
Kontrol penerimaan harus gagal dengan biaya murah dan konsisten. Di gateway, terapkan kuota tenant kontraktual dan batas trafik kasar. Pada setiap instans layanan, gunakan saturasi lokal untuk melindungi tugas yang memiliki sumber daya tersebut. Jika layanan mikro downstream kelebihan beban, tolak di upstream sebelum melakukan pekerjaan yang nantinya akan dibuang. Teruskan tingkat kepentingan permintaan di sepanjang jalur pemanggilan sehingga pesanan yang sama tidak diterima oleh satu lapisan lalu ditolak secara acak setelah menghabiskan sumber daya di lapisan lain.
Gunakan kebijakan prioritas dengan reservasi kapasitas eksplisit:
| Kelas | Tindakan saat kelebihan beban | Alasan |
|---|---|---|
| Pengiriman pesanan | Konkurensi yang dicadangkan; tolak hanya setelah batasnya sendiri tercapai | Mempertahankan jalur kritis tanpa memberikan kapasitas tak terbatas |
| Pemeriksaan ketersediaan | Lebih memilih data cache berumur pendek dengan kontrak kesegaran yang jelas; jika tidak, tolak | Mengurangi beban kerja downstream tanpa mengarang jawaban |
| Rekonsiliasi batch | Jeda penerimaan dan lanjutkan dari progres yang tersimpan nanti | Pekerjaan ini penting tetapi tidak memerlukan batas waktu interaktif |
Prioritas tanpa keadilan dapat mematikan tenant kecil. Terapkan kuota tenant atau penjadwalan yang adil di dalam sebuah kelas, dan pertahankan porsi minimum untuk pemulihan atau trafik kontrol. Hindari membuat puluhan tingkat prioritas: operator harus dapat memprediksi permintaan mana yang akan diterima selama insiden terjadi.
Ketika batas tercapai, berikan respons penolakan sebelum pemrosesan database atau dependensi dilakukan. HTTP 503 merepresentasikan kelebihan beban sementara dan dapat menyertakan Retry-After; ini tidak memberikan izin bagi setiap klien untuk mencoba lagi secara bersamaan. Klien menggunakan backoff eksponensial berbatas dengan jitter, batas waktu, dan anggaran percobaan ulang. Lakukan percobaan ulang pada satu lapisan yang sesuai, bukan di setiap lapisan. Pembuatan pesanan menggunakan kembali kunci idempoten dan memeriksa hasil sebelumnya setelah terjadi batas waktu yang ambigu. Permintaan yang batas waktu pemanggilnya telah kedaluwarsa dibatalkan agar server tidak menyelesaikan pekerjaan yang sia-sia.
Degradasi halus mengurangi biaya daripada sekadar menolak. Ketersediaan dapat melewati pengayaan opsional atau menggunakan cache dengan usia berbatas jika kontrak produk mengizinkannya. Konsumen batch dapat berhenti menarik pesan. Fallback yang melaporkan stok usang sebagai stok terkini adalah tindakan yang tidak tepat; jika kesegaran data wajib, kembalikan hasil eksplisit bahwa layanan tidak tersedia. Latih jalur degradasi secara terus-menerus pada sebagian kecil trafik karena jalur darurat yang tidak pernah digunakan cenderung gagal saat dibutuhkan.
Autoscaling, limpahan regional, dan peningkatan kapasitas tetap berguna, tetapi mereka beroperasi setelah kontrol penerimaan. Penskalaan berdasarkan jumlah permintaan mentah dapat menambah instans saat trafik ringan dan tertinggal saat trafik berat; sertakan konkurensi, usia antrean, atau saturasi sumber daya. Instans baru harus melakukan pemanasan koneksi (warm-up) sebelum menerima beban penuh. Failover memerlukan pemeriksaan kapasitas tujuan. Tak satu pun dari mekanisme ini membenarkan penghapusan batas lokal.
Pemulihan menggunakan ambang batas keluar yang lebih rendah daripada ambang batas masuk. Setelah pekerjaan yang sedang berjalan, usia antrean, dan kesehatan dependensi tetap berada di bawah ambang batas tersebut selama periode penahanan (hold period), tingkatkan beban yang diterima secara bertahap. Pertahankan reservasi prioritas hingga latensi normal stabil. Histeresis dan peningkatan bertahap ini mencegah sistem berpindah-pindah antara kondisi terbuka dan kelebihan beban atau membanjiri dependensi yang baru pulih sebagian.
Validasi kebijakan di luar uji kapasitas nominal. Putar ulang kombinasi biaya permintaan produksi, lalu naikkan kedatangan dari 3.000 menjadi 8.000 permintaan per detik sambil memperlambat inventaris dan menunda autoscaling selama tiga menit. Tambahkan percobaan ulang klien yang tersinkronisasi, satu tenant yang abusif, batas waktu yang kedaluwarsa, dan pemulihan dependensi. Pastikan antrean dan memori berbatas, penggunaan worker dan koneksi stabil, penolakan berbiaya murah, keberhasilan pesanan dalam reservasinya, keadilan tenant, degradasi yang jujur, amplifikasi percobaan ulang terkendali, dan pemulihan bertahap ke kondisi normal. Ukur operasi berguna yang selesai secara terpisah dari permintaan yang diterima dan percobaan downstream.
Contoh Jawaban Berkualitas Tinggi
"Kapasitas 3.000 permintaan per detik yang berkelanjutan adalah hasil uji beban untuk satu kombinasi permintaan tertentu, jadi saya akan terlebih dahulu mengidentifikasi sumber daya pada batas tersebut. Selama perlambatan inventaris, panggilan yang sedang berjalan dan penggunaan koneksi jauh lebih berguna daripada sekadar tingkat permintaan. Saya akan menetapkan batas konkurensi per instans yang telah diuji untuk layanan tersebut, bulkhead yang lebih kecil untuk inventaris, dan antrean kecil yang waktu tunggunya masih sesuai dengan batas waktu permintaan. Begitu salah satu batas tercapai, layanan akan menolak sebelum melakukan pekerjaan yang berat.
Saya akan mengklasifikasikan trafik menjadi pengiriman pesanan, ketersediaan, dan rekonsiliasi. Pesanan menerima kapasitas yang dicadangkan tetapi tetap memiliki batas tegas. Ketersediaan dapat menggunakan cache berumur pendek hanya jika API secara terbuka menyatakan kontrak kesegaran tersebut. Rekonsiliasi dijeda dan dilanjutkan dari progres yang tersimpan. Di setiap kelas, saya akan menerapkan keadilan tenant, sehingga satu pelanggan tidak dapat mengambil seluruh alokasi cadangan. Saya juga akan meneruskan prioritas ke downstream untuk menghindari pembuangan sumber daya pada permintaan yang nantinya dibuang secara acak oleh layanan berikutnya.
Kelebihan beban sementara mengembalikan status 503 dan, jika kita dapat memperkirakannya, Retry-After. Klien tetap memerlukan backoff berbatas, jitter, batas waktu, dan anggaran percobaan ulang bersama. Hanya satu lapisan yang melakukan percobaan ulang, dan operasi tulis pesanan menggunakan kembali kunci idempoten. Pemanggil yang kedaluwarsa membatalkan pekerjaan downstream.
Autoscaling adalah loop kapasitas yang lebih lambat karena instans memerlukan waktu tiga menit. Saya akan melakukan penskalaan berdasarkan sinyal saturasi dan memanaskan instans baru, sementara kontrol penerimaan lokal menjaga armada yang ada tetap bertahan. Pemulihan memerlukan ambang batas keluar yang lebih rendah dan peningkatan beban bertahap.
Buktinya adalah uji kelebihan beban pada 8.000 permintaan per detik dengan inventaris lambat, penskalaan tertunda, percobaan ulang, biaya permintaan yang bervariasi, dan tenant yang bising. Saya mengharapkan memori dan antrean yang berbatas, throughput berguna yang stabil, reservasi dan keadilan pesanan yang dijanjikan, penolakan berbiaya rendah, tidak adanya badai percobaan ulang (retry storm), dan pemulihan terkendali setelah inventaris kembali normal."
Kesalahan Umum
- Menaikkan batas antrean hingga kesalahan hilang → Permintaan yang diterima menunggu lebih lama, menghabiskan memori, kedaluwarsa, dan memicu percobaan ulang tanpa menambah kapasitas eksekusi → Batasi antrean berdasarkan sisa batas waktu dan tolak sejak awal.
- Mendeteksi kelebihan beban hanya dari permintaan per detik → Biaya permintaan dan latensi dependensi dapat berubah, sehingga tingkat yang sama bisa aman atau justru membawa bencana → Gunakan pekerjaan lokal yang sedang berjalan, usia antrean, saturasi sumber daya, dan connection pool dependensi.
- Membiarkan autoscaling menjadi pertahanan pertama → Penundaan tiga menit memungkinkan antrean dan percobaan ulang menggoyahkan armada yang ada → Pertahankan batas penerimaan lokal, lalu lakukan penskalaan untuk memulihkan kapasitas cadangan.
- Memberikan prioritas tak terbatas pada trafik kritis → Hal itu dapat menghabiskan sumber daya yang sama dan mematikan pekerjaan pemulihan → Cadangkan kapasitas tetapi tetap pertahankan batas tegas dan keadilan.
- Membuang beban secara acak di setiap layanan mikro → Pekerjaan upstream telah terkonsumsi sebelum penolakan acak di tahap hilir, mengurangi keberhasilan berguna secara end-to-end → Teruskan tingkat kepentingan dan tolak seawal mungkin begitu titik hambatan diketahui.
- Mengembalikan 503 dan membiarkan setiap klien mencoba ulang → Percobaan ulang yang tersinkronisasi melipatgandakan beban berlebih → Gunakan jitter, batas waktu, satu lapisan percobaan ulang, dan anggaran percobaan ulang.
- Menyajikan fallback data usang tanpa penandaan → Sistem tampak tersedia padahal melanggar semantik inventaris → Buka kontrak kesegaran secara transparan atau berikan kegagalan secara eksplisit.
- Memulihkan trafik penuh secara langsung → Dependensi yang baru pulih akan kelebihan beban kembali → Gunakan histeresis, probe berbatas, dan peningkatan penerimaan bertahap.
- Hanya melacak trafik yang diterima → Tingkat penerimaan yang tinggi dapat menyembunyikan batas waktu habis, pekerjaan yang terbuang, dan percobaan ulang → Ukur penyelesaian yang berguna, biaya penolakan, pemborosan batas waktu, dan amplifikasi percobaan.
Pertanyaan Lanjutan dan Tanggapan
Pertanyaan Lanjutan 1: Mengapa tidak menyelesaikan masalah ini dengan rate limiter terdistribusi?
Rate limiter terdistribusi berguna untuk kuota kontraktual, kontrol penyalahgunaan, dan pembentukan trafik (traffic shaping) sebelum permintaan mencapai layanan. Mekanisme ini sendiri tidak dapat mengamati bahwa latensi inventaris telah meningkatkan biaya dari setiap permintaan yang diizinkan. Pertahankan batas gateway, lalu tambahkan perlindungan konkurensi dan antrean lokal pada pemilik sumber daya. Jika biaya permintaan stabil dan layanan memiliki satu bottleneck, pembatasan laju yang konservatif mungkin merupakan solusi yang lebih sederhana dan memadai.
Pertanyaan Lanjutan 2: Bagaimana Anda memilih batas konkurensi?
Mulailah dari uji beban yang menggunakan kombinasi permintaan produksi dan temukan konkurensi tertinggi yang masih memenuhi target latensi dan sumber daya dengan kapasitas cadangan. Ulangi pengujian dengan simulasi perlambatan dependensi. Hubungan kondisi stabil (steady-state) antara konkurensi, throughput, dan waktu dapat memberikan pemeriksaan kewajaran (sanity check), tetapi tidak menjamin kapasitas saat terjadi lonjakan kedatangan atau variasi biaya. Terapkan batas dalam mode observe-only, lakukan canary rejection, lalu lakukan penegakan penuh; tinjau kembali saat kode, ukuran instans, atau dependensi berubah.
Pertanyaan Lanjutan 3: Bagaimana jika 90% trafik ditandai sebagai kritis?
Jika demikian, label tersebut tidak lagi berguna untuk membuat keputusan penerimaan. Tentukan kekritisan berdasarkan operasi bisnis, autentikasi pihak yang boleh menetapkannya, batasi setiap kelas, dan cadangkan hanya porsi yang terukur. Di dalam kelas kritis, gunakan keadilan tenant atau prioritas stabil per pengguna sehingga kelebihan beban tidak secara sewenang-wenang menguntungkan klien yang paling bising. Jika permintaan yang benar-benar kritis melebihi kapasitas fisik, sebagian pekerjaan kritis tetap harus gagal; kontrak harus menyatakan mekanismenya.
Pertanyaan Lanjutan 4: Bisakah konkurensi adaptif membuat desain menjadi lebih baik?
Konkurensi adaptif dapat mengikuti perubahan waktu layanan lebih dekat daripada batas statis, tetapi latensi yang berfluktuasi dan umpan balik yang tertunda dapat menyebabkan osilasi atau shedding yang salah. Mulailah dengan batas statis yang telah diuji. Tambahkan kontrol adaptif hanya jika memiliki batas minimum dan maksimum, sinyal yang dihaluskan, histeresis, nilai fallback yang stabil, dan uji pemutaran ulang yang mencakup penurunan performa cepat dan pemulihan lambat.
Pertanyaan Lanjutan 5: Di mana load shedding seharusnya dilakukan dalam grafik pemanggilan yang dalam (deep call graph)?
Pemilik sumber daya memerlukan garis pertahanan terakhir di tingkat lokal. Begitu layanan tersebut memberi sinyal kelebihan beban, lapisan upstream harus menghentikan pekerjaan lebih awal dan mempertahankan keputusan kekritisan yang sama di sepanjang jalur panggilan. Shedding hanya di tepi (edge) tidak memiliki status downstream yang presisi; shedding hanya di tingkat daun (leaf) membuang-buang pekerjaan upstream. Desain yang praktis menggabungkan kebijakan edge yang kasar, perlindungan lokal, dan sinyal kelebihan beban yang dapat ditindaklanjuti oleh pemanggil upstream.
Pertanyaan Lanjutan 6: Metrik produksi mana yang menunjukkan bahwa kebijakan tersebut berfungsi?
Lacak penyelesaian berguna dan latensi berdasarkan operasi dan prioritas; permintaan yang diterima, diantrekan, didegradasi, dan ditolak; usia antrean tertua; pekerjaan yang sedang berjalan; saturasi CPU, memori, worker, dan koneksi; pekerjaan yang batas waktunya kedaluwarsa; keadilan per-tenant; percobaan fisik per permintaan logis; penundaan kesiapan autoscaling; dan waktu yang dihabiskan dalam mode overload. Berikan peringatan jika reservasi kritis hilang, kelebihan beban berkepanjangan, biaya penolakan mendekati biaya permintaan normal, atau jika peningkatan pemulihan berulang kali mengalami kemunduran.