Perintah dan konteks
Aplikasi kolaborasi real-time harus mengirimkan operasi dokumen secara andal sambil mengirimkan posisi kursor dan heartbeat yang boleh terbuang (dropped). Tim memilih WebTransport tetapi belum mendefinisikan perilaku penutupan, perubahan jaringan, rekoneksi, backpressure, atau pembersihan. Rancang siklus hidupnya dan jelaskan batasan antara reliable stream, unreliable datagram, dan koneksi HTTP/3.
W3C WebTransport API mengekspos reliable stream dan unreliable datagram; RFC 9297 mendefinisikan HTTP datagram. Jawaban yang kuat memisahkan sesi aplikasi dari transport dan tidak memperlakukan close() sebagai bukti bahwa setiap pesan bisnis telah terkirim.
Hal yang diuji oleh pewawancara
- Membedakan penutupan sesi, penutupan stream, hilangnya datagram, dan kegagalan jaringan.
- Merancang rekoneksi, pemulihan sesi, nomor urut (sequence numbers), idempotensi, dan snapshot.
- Menangani backpressure stream, batas datagram, klien lambat, dan pembatasan sumber daya.
- Mendefinisikan kode penutupan, alasan, batas waktu (timeouts), dan observabilitas.
- Menetapkan batasan yang jelas untuk browser, proksi, HTTP/3, dan fallback.
Pertanyaan klarifikasi
- Pesan mana yang harus andal dan berurutan, dan mana yang boleh diabaikan atau disusutkan menjadi nilai terbaru saja?
- Bisakah sebuah sesi dipulihkan saat terjadi perubahan jaringan? Berapa lama waktu pemulihan dan riwayat operasi yang dapat diterima?
- Batasan apa yang berlaku untuk sesi konkuren, stream, dan laju datagram per pengguna?
- Apakah penutupan diinisiasi oleh pengguna, pemeliharaan (maintenance), masa berlaku autentikasi habis, kelebihan beban (overload), atau kesalahan protokol?
- Apakah browser dan proksi mendukung WebTransport melalui HTTP/3, dan apa fallback eksplisitnya?
Jawaban 30 detik
Pisahkan ID sesi aplikasi dari satu koneksi WebTransport. Kirim operasi yang andal melalui stream dengan nomor urut dan kunci idempotensi; kirim kursor dan heartbeat sebagai datagram yang toleran terhadap kehilangan data (lossy). Saat terjadi kegagalan, pertahankan status sesi di sisi server secara singkat; sambungkan kembali dengan exponential backoff dan urutan terakhir yang dikonfirmasi, lalu pulihkan dari snapshot ditambah delta. Untuk penutupan yang baik (graceful close), hentikan pekerjaan baru, kuras (drain) reliable stream, kirim penanda penyelesaian aplikasi, tutup dengan kode, dan terapkan batas waktu ketat (hard timeout). Batasi setiap buffer dan sumber daya.
Jawaban mendalam
1. Membentuk sesi aplikasi dan transport
ID sesi aplikasi merepresentasikan keanggotaan logis pengguna di ruang kolaborasi; instans WebTransport adalah satu koneksi jaringan. Setelah handshake, validasi origin, autentikasi, penyewa (tenant), dan izin ruang, buat ID koneksi, lalu petakan ke sesi aplikasi. Rekoneksi akan membuat ID koneksi baru dan tidak pernah memberikan sesi pengguna lain.
Simpan urutan operasi terakhir yang dikonfirmasi, versi snapshot, langganan (subscriptions), dan masa kedaluwarsa. Setelah terputus, tandai status aplikasi sebagai ditangguhkan (suspended) selama TTL singkat sebelum dilepaskan.
2. Memilih stream atau datagram per pesan
Operasi dokumen, perubahan izin, dan konfirmasi (acknowledgements) menggunakan reliable stream dengan pembingkaian (framing) eksplisit, versi, nomor urut, dan kunci idempotensi. Kursor, metrik langsung, dan heartbeat menggunakan datagram, dengan penerima membuang stempel waktu atau versi yang usang. Jangan pernah menempatkan peristiwa bisnis yang wajib terkirim ke dalam datagram.
Datagram tidak memberikan jaminan pengiriman, pengurutan, atau transmisi ulang, serta memiliki batasan ukuran jalur dan implementasi. Ukur kehilangan data dan latensi, kurangi frekuensi, atau kirim hanya status terbaru. Reliable stream menggunakan backpressure WritableStream alih-alih antrean memori tanpa batas.
3. Menangani backpressure dan klien yang lambat
Tetapkan jendela pengiriman, batas ack tertunda, dan ukuran frame maksimum per reliable stream. Saat penulisan tetap tertunda, jeda produsen; jika batas waktu habis, putuskan sambungan atau kurangi langganan non-kritis. Gunakan token bucket dan anggaran per sesi untuk datagram; membuang kursor lama lebih baik daripada memblokir operasi dokumen.
Batasi juga jumlah sesi, jumlah stream, proses decoding konkuren, dan total memori. Agregasikan metrik berdasarkan penyewa sehingga satu klien yang lambat tidak dapat menghabiskan event loop.
4. Merancang pemutusan sambungan dan pemulihan
Klien menetapkan nomor urut lokal dan kunci idempotensi untuk operasi yang andal serta memajukan checkpoint setelah konfirmasi. Handshake rekoneksi membawa ID sesi, urutan terakhir yang dikonfirmasi, dan kapabilitas. Server memverifikasi kepemilikan sesi dan mengembalikan snapshot, delta, atau kesalahan yang tidak dapat dipulihkan.
Jeda efek samping baru selama pemulihan agar koneksi lama dan baru tidak dapat mengirimkan data secara bersamaan. Gunakan epoch untuk membatalkan penulisan dari koneksi lama dan buka kembali produsen hanya setelah pemulihan selesai.
5. Merancang graceful shutdown
Selama pemeliharaan, siarkan status draining, tolak sesi baru, dan hentikan datagram non-kritis. Biarkan reliable stream menyelesaikan frame saat ini dan mengirimkan penanda penyelesaian aplikasi, lalu tutup sesi setelah masa tunggu yang dibatasi. close() browser mengomunikasikan penutupan sesi dan informasi penutupan; ini bukan konfirmasi bisnis.
Klasifikasikan kode penutupan untuk keluar normal, masa berlaku autentikasi habis, beban berlebih, kesalahan protokol, dan pemeliharaan. Buat alasan penutupan tetap singkat dan tidak sensitif. Pada hard timeout, segera lepaskan sumber daya dan catat operasi yang belum selesai.
6. Memeriksa ulang autentikasi dan perubahan jaringan
Setiap koneksi baru atau yang dipulihkan memvalidasi ulang kredensial, origin, penyewa, dan izin ruang. Jangan memulihkan hanya berdasarkan ID sesi saja. Perubahan jaringan dapat mengubah alamat; pemulihan aplikasi menggunakan koneksi baru, sementara epoch mencegah jalur lama melakukan penulisan.
Jika WebTransport atau HTTP/3 tidak tersedia, negosiasikan fallback secara eksplisit dan nyatakan kembali perbedaan keandalan, latensi, dan keamanan. Jangan menerapkan semantik penutupan WebSocket ke datagram.
7. Mengamati dan menguji mode kegagalan
Catat pembuatan koneksi, kegagalan handshake, kode dan alasan penutupan, backpressure stream, datagram yang terbuang, jumlah rekoneksi, durasi pemulihan, dan operasi yang belum dikonfirmasi. Jangan mencatat token atau konten dokumen sensitif ke dalam log. Segmentasikan metrik berdasarkan klien, jenis jaringan, dan penyewa.
Uji pemeliharaan, perubahan jaringan seluler, pemblokiran proksi HTTP/3, klien lambat, lonjakan datagram, dan rekoneksi duplikat. Kriteria penerimaan mencakup tidak adanya efek samping duplikat, batas pemulihan yang eksplisit, pembersihan sesi kedaluwarsa, dan latensi penutupan yang dibatasi.
Jawaban model
Saya akan memisahkan sesi aplikasi dari koneksi WebTransport. Operasi dokumen yang andal menggunakan stream dengan nomor urut dan kunci idempotensi; kursor dan heartbeat menggunakan datagram yang toleran terhadap kehilangan. Klien menyimpan checkpoint dan menyambung kembali dengan ID sesi serta urutan terakhir yang dikonfirmasi. Server memverifikasi pengguna dan penyewa, memulihkan dari snapshot ditambah delta, dan menggunakan epoch untuk membatalkan penulisan lama.
Graceful shutdown memasuki tahap draining, menghentikan pesan baru dan datagram non-kritis, menguras reliable stream, mengirimkan penanda penyelesaian aplikasi, lalu menutup dengan kode dan hard timeout. Batasi sesi, stream, buffer, dan rekoneksi; pantau kehilangan data, backpressure, alasan penutupan, dan waktu pemulihan. Negosiasikan fallback apa pun secara eksplisit.
Kesalahan umum
- Memperlakukan datagram sebagai pesan yang andal atau
close()sebagai konfirmasi bisnis. - Membuat koneksi baru setelah kegagalan tanpa checkpoint, epoch, atau kunci idempotensi.
- Menampung data klien yang lambat ke dalam buffer secara terus-menerus hingga menghabiskan memori atau event loop.
- Memulihkan berdasarkan ID sesi tanpa memvalidasi ulang pengguna, penyewa, origin, dan izin.
- Melewatkan proses draining, hard timeout, atau audit operasi yang belum selesai selama penutupan.
- Mengabaikan pemblokiran HTTP/3, dukungan browser, dan perilaku proksi.
- Mencatat token lengkap, konten dokumen, atau alasan penutupan yang sensitif ke dalam log.
Pertanyaan lanjutan dan jawaban
Apa yang seharusnya dikirim melalui datagram?
Nilai berumur pendek yang toleran terhadap kehilangan data seperti kursor, pose sementara, dan heartbeat berfrekuensi tinggi. Operasi bisnis yang wajib sampai menggunakan reliable stream.
Bagaimana Anda mencegah duplikasi operasi setelah rekoneksi?
Tetapkan kunci idempotensi dan nomor urut, lakukan deduplikasi berdasarkan sesi dan epoch di server, dan hanya majukan checkpoint setelah ada konfirmasi.
Bagaimana penutupan saat pemeliharaan seharusnya bekerja?
Hentikan sesi baru dan siarkan status draining, hentikan datagram non-kritis, kuras reliable stream, kirim penanda penyelesaian, lalu tutup secara normal. Paksa pembersihan pada hard timeout.
Apa yang terjadi jika TTL sesi kedaluwarsa?
Kembalikan kesalahan yang tidak dapat dipulihkan dan wajibkan autentikasi ulang serta bergabung kembali. ID sesi lama tidak boleh memperpanjang izin.
Bagaimana jika datagram terlalu besar atau tingkat kehilangan data tinggi?
Batasi ukuran dan laju, kompresi atau gabungkan status (coalesce), dan simpan hanya nilai terbaru. Peristiwa bisnis tidak boleh bergantung pada datagram yang tidak andal.
Bagaimana Anda membuktikan bahwa fallback mempertahankan semantik?
Dokumentasikan perbedaan keandalan, pengurutan, pemulihan, dan autentikasi per protokol. Uji pemutusan sambungan, pemblokiran proksi, klien lambat, dan rekoneksi duplikat sambil mengukur efek samping duplikat.