Topik wawancara representatif

Bagaimana perambatan tenggat waktu (deadline propagation) dan pembatalan (cancellation) seharusnya bekerja di seluruh RPC?

BackendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Sebuah permintaan memiliki anggaran 2 detik dan memanggil beberapa layanan. Bagaimana Anda menyebarkan tenggat waktu dan pembatalan agar pekerjaan di downstream tidak berjalan lebih lama dari permintaan aslinya?

Pertanyaan dan cakupan

Anda sedang merancang jalur permintaan di mana layanan A memanggil B dan B memanggil C. Klien memberikan batas waktu 2 detik dari penerimaan hingga respons. A dapat menghabiskan 500 ms sebelum memanggil B; B dapat memanggil C dan layanan audit yang tidak kritis. Jelaskan kontrak untuk tenggat waktu (deadline), pembatalan (cancellation), percobaan ulang (retry), dan keteramatan (observability).

Asumsikan setiap hop dapat gagal secara independen, jam (clock) tidak tersinkronisasi sempurna, dan RPC read-only yang mengalami batas waktu (timeout) hanya dapat dicoba ulang jika operasinya bersifat idempoten. Tujuannya adalah menghentikan pekerjaan yang sia-sia sambil tetap menjaga anggaran yang cukup untuk serialisasi dan transportasi respons.

Apa yang sedang diuji oleh pewawancara

Rubrik desain sistem tingkat staf InterviewStack mengharapkan kandidat untuk memperjelas batasan latensi dan kegagalan, mengidentifikasi bottleneck, dan menjustifikasi trade-off. Jawaban yang kuat mengubah sinyal-sinyal tersebut menjadi kontrak anggaran yang eksplisit:

  • Satu tenggat waktu permintaan absolut ditetapkan di edge; setiap hop menurunkan sisa anggarannya alih-alih membuat batas waktu (timeout) baru yang terpisah.
  • Pembatalan mengikuti pohon panggilan, termasuk cabang hedged atau paralel, sehingga respons yang selesai akan menghentikan pekerjaan yang tidak lagi berguna.
  • Percobaan ulang (retry) menggunakan sisa anggaran yang sama dan dibatasi oleh keidempotenan serta batas jumlah percobaan (attempt cap).
  • Metrik membedakan antara habisnya tenggat waktu, pembatalan oleh pemanggil, penundaan antrean, penolakan downstream, dan pekerjaan berguna yang diselesaikan setelah pembatalan.

Pertanyaan klarifikasi sebelum menjawab

  1. Apakah batas 2 detik merupakan SLO yang terlihat oleh pengguna atau batas waktu kebenaran mutlak (hard correctness deadline)? Batas waktu mutlak membuat hasil yang terlambat menjadi tidak valid; SLO mengizinkan jalur penyelesaian latar belakang yang dibatasi dengan hati-hati.
  2. Panggilan mana yang penting bagi respons? Panggilan audit atau rekomendasi yang tidak kritis dapat dipisahkan, disampling, atau dikembalikan dengan respons terdegradasi; otorisasi penagihan tidak dapat diperlakukan demikian.
  3. Apakah operasi penulisan (write) bersifat idempoten? Anggaran retry aman untuk operasi read atau perintah ber-kunci idempoten, tetapi tidak aman untuk efek samping yang tidak terlindungi.
  4. Apakah stack RPC menyebarkan konteks secara otomatis? Jika tidak, tentukan kontrak interceptor atau middleware dan uji di setiap batas bahasa.
  5. Apakah kita memerlukan pekerjaan untuk selesai setelah pembatalan, seperti ekspor dengan checkpoint? Pengecualian tersebut memerlukan kontrak pekerjaan yang persisten (durable job contract) alih-alih mengabaikan pembatalan secara diam-diam.

Kerangka jawaban 30 detik

"Saya menetapkan satu tenggat waktu di ingress dan membawa sisa anggaran melalui konteks RPC. Setiap layanan memeriksa pembatalan sebelum mengantre dan selama pekerjaan yang memakan waktu lama, lalu meneruskan anggaran turunan yang lebih pendek yang menyisakan ruang jeda (slack) untuk respons dan jaringan. Percobaan ulang hanya menggunakan waktu yang tersisa, dibatasi, dan membutuhkan idempotensi. Ketika pemanggil mendapatkan hasil atau membatalkan, sinyal pembatalan menyebar (fan out) ke setiap cabang. Saya mengukur tingkat terlampauinya tenggat waktu, sisa anggaran di setiap hop, waktu antrean, latensi pembatalan, dan pekerjaan yang terlambat, kemudian melakukan uji beban pada rantai panggilan serta menyuntikkan dependensi yang lambat atau dibatalkan."

Jawaban mendalam langkah demi langkah

1. Menetapkan dan merepresentasikan anggaran

Edge mencatat tenggat waktu absolut, misalnya t0 + 2s. Memperlakukannya sebagai sebuah titik waktu mencegah setiap hop menambahkan 2 detik baru secara diam-diam. Sebuah layanan menghitung remaining = deadline - now dan mencadangkan margin lokal kecil untuk serialisasi dan transit jaringan. Margin tersebut adalah sebuah kebijakan, bukan konstanta universal; validasikan dengan data latensi persentil.

Panduan gRPC membedakan tenggat waktu (deadline) dari batas waktu (timeout) dan merekomendasikan tenggat waktu klien yang eksplisit. Panduan ini juga mengonversi tenggat waktu yang dirambatkan menjadi sisa waktu sehingga perbedaan waktu jam (clock skew) tidak membuat server downstream menunggu melebihi anggaran awal. Oleh karena itu, kontrak komunikasi jaringan (wire contract) harus membawa konteks tenggat waktu melalui pustaka RPC, bukan header aplikasi bentuk bebas yang dapat dilupakan oleh pemanggil.

2. Menghabiskan anggaran berdasarkan jalur kritis

Misalkan A menghabiskan 500 ms. A meneruskan paling banyak 1,5 detik ke B. Jika B membutuhkan 400 ms untuk pekerjaan lokal dan memanggil C, B meneruskan nilai terkecil antara sisa anggarannya dikurangi margin respons 100 ms dan batas atas spesifik layanan C. Panggilan paralel berbagi tenggat waktu induk yang sama; mereka tidak masing-masing menerima 1,5 detik penuh.

Penerimaan antrean memeriksa sisa anggaran. Jika estimasi penundaan antrean sudah melampauinya, tolak dengan cepat (reject fast) atau kembalikan respons terdegradasi yang terdokumentasi. Ini mencegah permintaan menempati worker setelah keberhasilan tidak lagi memungkinkan.

3. Merambatkan pembatalan, bukan hanya kedaluwarsa

Kedaluwarsa tenggat waktu hanyalah salah satu alasan pembatalan; pemanggil yang menutup koneksi atau cabang lain yang memenangkan hedging adalah alasan lainnya. Setiap RPC turunan menerima konteks pembatalan induk. Worker memeriksanya sebelum langkah-langkah yang memakan banyak sumber daya dan pada interval tertentu selama loop, lalu melepaskan izin (permit) dan menutup stream.

Google SRE memperingatkan bahwa perambatan tenggat waktu saja masih dapat membocorkan pekerjaan ketika panggilan yang lebih dalam gagal lebih awal. Pembatalan harus bergerak kembali ke atas dan menyebar (fan out) ke panggilan setingkat (sibling). Pekerjaan persisten dengan checkpoint dapat menyelesaikan checkpoint yang aman, tetapi itu adalah alur kerja asinkron eksplisit dengan API statusnya sendiri, bukan RPC sinkron yang mengabaikan pembatalan.

4. Membuat retry sadar akan anggaran

Hitung attempt_deadline = min(parent_remaining - response_margin, per-attempt_cap). Berhenti ketika percobaan berikutnya tidak dapat selesai sebelum tenggat waktu induk. Coba ulang hanya kegagalan sementara dan hanya operasi yang secara alami idempoten atau dilindungi oleh kunci idempotensi. Permintaan hedged menggunakan anggaran induk yang sama dan membatalkan percobaan yang kalah segera setelah satu respons yang dapat diterima tiba.

Jangan menggabungkan timeout retry yang panjang dengan circuit breaker yang tidak memiliki pengetahuan tentang sisa anggaran. Catat nomor percobaan dan tenggat waktu asli sehingga layanan downstream dapat membedakan permintaan baru dari retry yang hampir kedaluwarsa.

5. Menentukan semantik kegagalan yang dapat diamati

Kembalikan status stabil untuk habisnya tenggat waktu, seperti DEADLINE_EXCEEDED pada gRPC, dan pertahankan penyebab asli pembatalan dalam log. Bidang trace harus mencakup tenggat waktu asli, sisa anggaran saat masuk dan keluar, penundaan antrean, jumlah percobaan, dan latensi dari pembatalan hingga berhenti. Buat peringatan (alert) untuk anggaran yang dihabiskan dalam antrean dan pekerjaan berguna setelah pembatalan, bukan hanya latensi menyeluruh (end-to-end).

Uji kontrak tersebut dengan harness integrasi tiga-hop: tunda C melebihi sisa anggaran, batalkan di A saat B sedang mengantre, buat hedge pertama berhasil, dan suntikkan perbedaan offset jam. Pastikan bahwa tidak ada turunan yang berjalan melebihi tenggat waktu induk kecuali checkpoint yang dideklarasikan secara eksplisit, bahwa retry berhenti, dan bahwa izin dilepaskan.

Contoh jawaban berkualitas tinggi

"Saya akan menjadikan ingress sebagai pemilik tunggal dari tenggat waktu 2 detik tersebut. A menerimanya dalam konteks RPC, dan setelah 500 ms A meneruskan sisa anggaran ke B. B mengurangi margin responsnya sendiri sebelum memanggil C; cabang paralel tetap berbagi tenggat waktu induk yang sama. Setiap turunan mengamati pembatalan sebelum mengantre dan saat melakukan pekerjaan yang dibatasi, dan pembatalan menyebar ketika klien terputus atau hedge menang. Percobaan ulang dibatasi pada sisa anggaran dan membutuhkan idempotensi. Panggilan audit yang terlambat dapat dipisahkan menjadi pekerjaan persisten, tetapi respons kritis tidak dapat berpura-pura bahwa pekerjaan yang terlambat itu berguna. Saya akan membuktikan kontrak tersebut dengan dependensi lambat yang disuntikkan, penundaan antrean, race condition pembatalan, clock skew, dan trace yang menunjukkan anggaran di setiap hop."

Kesalahan umum

  • Memberikan timeout baru pada setiap hop → pohon panggilan dapat berjalan selama N kali lipat dari anggaran pengguna → sebarkan satu tenggat waktu dan hitung sisa waktu.
  • Menyebarkan kedaluwarsa tetapi mengabaikan pembatalan dari pemanggil → permintaan hedged dan yang ditinggalkan tetap mengonsumsi worker → sebarkan konteks pembatalan ke seluruh cabang dan ukur latensi penghentian.
  • Mencoba ulang setiap timeout → penulisan non-idempoten dapat menduplikasi efek samping dan retry yang kedaluwarsa memperberat beban → wajibkan idempotensi, klasifikasikan kesalahan, dan batasi percobaan berdasarkan sisa anggaran.
  • Mengantre sebelum memeriksa anggaran → permintaan yang pasti gagal menempati kapasitas yang terbatas → tolak atau degradasi ketika penundaan antrean tidak sesuai dengan sisa waktu.
  • Menggunakan margin tetap tanpa pengukuran → muatan besar (large payload) gagal secara konsisten atau kelonggaran latensi terbuang sia-sia → turunkan margin dari persentil transportasi dan serialisasi.
  • Menyembunyikan pekerjaan yang terlambat sebagai keberhasilan → dasbor menunjukkan respons yang sehat sementara sumber daya bocor → pisahkan tenggat waktu sinkron dari pekerjaan ber-checkpoint yang eksplisit.

Tindak lanjut dan tanggapan

Bagaimana jika jam berbeda antar layanan?

Jangan membandingkan stempel waktu jam dinding (wall-clock) mentah dari mesin-mesin yang independen. Gunakan konversi sisa waktu dari pustaka RPC atau sebarkan batas waktu setelah mengurangi waktu yang telah berlalu. Tambahkan pengujian clock-offset ke dalam harness pengujian.

Haruskah tenggat waktu diperpanjang di downstream?

Hanya dengan mengubah kontrak produk menjadi pekerjaan asinkron. Memperpanjang batas waktu turunan sinkron tidak dapat membuat respons induk yang terlambat menjadi valid; hal itu hanya meningkatkan pekerjaan yang sia-sia.

Bagaimana cara mencadangkan anggaran untuk payload yang lambat?

Ukur latensi ekor (tail latency) serialisasi dan jaringan secara terpisah, cadangkan margin yang dibatasi, dan batasi ukuran payload atau gunakan streaming. Jika margin berulang kali menghabiskan anggaran, ubah SLO atau bentuk respons alih-alih meningkatkan setiap batas waktu secara diam-diam.

Apa yang bertahan dari pembatalan?

Hanya pekerjaan yang secara eksplisit persisten dan idempoten seperti penulisan checkpoint atau peristiwa audit. Pekerjaan tersebut harus dapat diamati di bawah pengenal pekerjaan (job identifier) dan tidak boleh menahan worker atau koneksi dari permintaan sinkron.

Sumber publik

Pertanyaan terkait