Topik temu duga representatif

Temu duga Kubernetes: bagaimanakah anda mereka bentuk pengekodan penstriman untuk respons LIST yang besar?

Reka bentuk sistemSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Bagaimanakah pelayan API Kubernetes harus mengekod secara penstriman respons LIST untuk puluhan ribu objek sambil mengekalkan format respons, ketekalan penomboran halaman, dan kegagalan yang boleh didiagnosis?

Soalan dan skop

Sebuah kluster mempunyai puluhan ribu Pod dan sumber tersuai, dan pengawal mengeluarkan permintaan LIST penuh selepas but semula. Pengekod lama mensiri keseluruhan tatasusunan items ke dalam satu penimbal bersebelahan, mewujudkan lonjakan memori pada pelayan API. Reka bentuk pengekodan penstriman dan terangkan skop JSON dan Kubernetes Protobuf, hubungannya dengan penomboran halaman limit/continue dan gzip, pemulihan klien, tekanan balik, kebolehcerapan, dan syarat pengunduran.

Perkara yang sedang diuji oleh penemu duga

  • Mengenal pasti lonjakan dalam penimbal pengekodan dan bukannya mengecilkan masalah kepada lebar jalur rangkaian semata-mata.
  • Memisahkan semantik pengekodan penstriman, penomboran halaman, pemampatan, dan pantauan (watch).
  • Mengekalkan struktur JSON/Protobuf, versi sumber, dan semantik ralat untuk satu respons LIST.
  • Mengendalikan klien yang perlahan, pemutusan sambungan, peningkatan penggunaan CPU, penimbalan proksi, dan keserasian klien lama.
  • Menentukan penanda aras yang boleh diulang, metrik, kenari (canary), dan pintu pengunduran (rollback gates).

Soalan penjelasan

  1. Adakah permintaan tersebut berskop ruang nama (namespace) atau seluruh kluster? Saiz objek, jumlah, dan permintaan LIST yang serentak menentukan bajet memori.
  2. Adakah klien mesti menerima satu respons lengkap, atau adakah ia boleh menggunakan limit/continue? Penomboran halaman mengehadkan saiz hasil tetapi tidak menggantikan pengoptimuman pengekodan pada bahagian pelayan.
  3. Adakah HTTP/2, gzip, atau proksi terbalik berada dalam laluan? Penimbalan proksi mengubah faedah hujung-ke-hujung bagi pembebasan memori semasa mengekod.
  4. Adakah JSON, Kubernetes Protobuf, atau kedua-duanya diperlukan? Liputan pengekod mengubah susunan pelaksanaan.

Rangka jawapan 30 saat

Mula-mula, saya akan menyandarkan lonjakan memori kepada pensirian keseluruhan tatasusunan items, kemudian menukar pengekod untuk menulis secara berperingkat: pancarkan awalan koleksi, enkod dan tulis setiap item, serta pancarkan akhiran. JSON dan Kubernetes Protobuf mengekalkan semantik sumber masing-masing; penomboran halaman mengawal saiz hasil dan pemampatan mengawal lebar jalur. Penimbal terhad dan tekanan balik penulisan mengendalikan klien yang perlahan. Saya akan mengukur lonjakan RSS, CPU pengekodan, masa untuk bait pertama, kependaman penyiapan, dan pemutusan sambungan, menguji kenari JSON terlebih dahulu, kemudian mengesahkan Protobuf, proksi, dan klien lama sebelum meluaskan pelaksanaan. Melepasi had pintu pencetus akan memulakan pengunduran.

Jawapan mendalam

1. Uraikan punca lonjakan memori

Laluan lama boleh memegang senarai objek, keadaan pengekodan perantaraan, dan penimbal respons lengkap sekali gus. Apabila bilangan objek bertambah, bait respons bertambah mengikut jumlah muatan items; permintaan LIST yang serentak menambah lonjakan masing-masing. Penstriman hanya menjanjikan pengurangan memori sementara pada peringkat pengekodan. Ia tidak menghapuskan memori yang diperlukan untuk pembacaan, cache, pengisihan, atau penapisan kebenaran. Sahkan kekangan genting (bottleneck) dengan profil timbunan (heap profiles) dan beban serentak sebelum menukar pengekod atau menambah had kadar.

2. Reka bentuk pengekod item demi item

Tulis medan koleksi tetap terlebih dahulu. Selepas pembukaan items, siri satu objek, tulisnya, dan lepaskan penimbal sementaranya sebelum memproses objek seterusnya. Jangan tambah item ke dalam rentetan bait tanpa had. Pelaksanaan Kubernetes menyasarkan pengekod koleksi JSON dan Protobuf serta menumpukan pada medan pukal items tanpa mengubah bentuk objek API.

text
write(listPrefix)
for item in items:
    encoded = encodeOne(item)
    writeWithBackpressure(encoded)
    release(encoded)
write(listSuffix)

Penstriman mengubah jangka hayat memori, bukan susunan objek, metadata, versi sumber, atau takrifan ralat. Jika klien terputus sambungan di pertengahan respons, hentikan pengekodan dan lepaskan item semasa; badan respons separa bukanlah LIST yang berjaya.

3. Asingkan penomboran halaman, pemampatan, dan pantauan (watch)

limit/continue membahagikan satu koleksi kepada halaman yang tekal, mengurangkan saiz satu permintaan dan membolehkan klien memproses secara berperingkat; ini memperkenalkan tamat tempoh token, but semula, dan gelung klien. Penstriman masih penting apabila satu halaman bersaiz besar kerana ia mengawal lonjakan pengekodan pada bahagian pelayan. gzip mengurangkan bait rangkaian, tetapi pemampat boleh menambah penimbalan, jadi ukur dasar siramannya (flush policy). watch ialah penstriman peristiwa berterusan dengan semantik pemulihan yang berbeza dan tidak boleh menggantikan satu LIST yang tekal.

4. Kendalikan tekanan balik dan proksi

Apabila soket perlahan, pengekod mesti mematuhi penulisan yang disekat serta pembatalan, dan menghadkan penimbalan bagi setiap sambungan. Jika tidak, pengekod "penstriman" masih boleh dipasang semula oleh proksi atau get laluan. Rekod masa bait pertama dan bait terakhir, dengan membezakan masa menunggu pengekodan, tekanan balik rangkaian, penimbalan proksi, dan pembacaan klien yang perlahan. Pemisahan bingkai HTTP/2 tidak membuktikan bahawa aplikasi telah melepaskan penimbal respons lengkapnya; sahkan timbunan pelayan dan laluan penulisan.

5. Keserasian, kenari, dan pengunduran

Kekalkan struktur wayar JSON/Protobuf dan rundingan kandungan tanpa perubahan, termasuk continue, versi sumber, dan ralat. Dayakan ciri ini terlebih dahulu untuk jenis sumber yang mempunyai banyak objek dan keserentakan yang rendah, bandingkan lonjakan RSS, CPU, kependaman bait pertama, kependaman penyiapan, pemutusan sambungan, dan kadar ralat API, kemudian luaskan. Jika proksi lama tidak dapat menerima respons berketul (chunked) atau termampat, kekalkan pintu ciri (feature gate) atau pilih pengekod lama berdasarkan keupayaan klien. Lakukan pengunduran berasaskan regresi lonjakan memori, kependaman P99, atau kadar ralat, dan bukannya daya pemprosesan purata semata-mata.

Contoh jawapan berkualiti tinggi

Saya akan menskopkan masalah ini kepada lonjakan pengekodan pada pelayan API. Saya akan menirunya dengan beban LIST serentak, kemudian memastikan pengekod memancarkan awalan koleksi, mensiri dan menulis setiap item, melepaskan penimbal sementaranya, dan memancarkan akhiran. Ini mengurangkan memori sementara pada peringkat pengekodan; ia tidak menghapuskan kos membaca, mengisih, atau memberi kebenaran kepada objek. JSON dan Kubernetes Protobuf mengekalkan bentuk wayarnya, limit/continue kekal sebagai penomboran halaman, gzip kekal sebagai kawalan lebar jalur, dan watch kekal sebagai kontrak peristiwa yang berbeza. Penulisan mematuhi tekanan balik soket dan pembatalan, manakala penimbalan proksi diukur secara berasingan. Saya akan menguji kenari JSON, kemudian Protobuf dan proksi utama, membandingkan lonjakan RSS, CPU pengekodan, masa bait pertama, kependaman penyiapan, dan pemutusan sambungan. Pintu ciri menyahdayakan ciri tersebut atau memilih pengekod lama apabila regresi melebihi garis dasar. Ujian merangkumi klien yang perlahan, pemutusan sambungan, senarai kosong, item besar, token sambungan yang tamat tempoh, dan klien lama.

Kesilapan lazim

  • Menambah penomboran halaman sahaja → satu halaman masih boleh menjadi besar dan ditimbal sepenuhnya → sahkan penomboran halaman dan penstriman item secara bersama.
  • Menganggap gzip sebagai penyelesaian memori → pemampatan boleh mengekalkan penimbal → ukur peringkat pengekodan, pemampatan, dan soket secara berasingan.
  • Menganggap pemisahan bingkai HTTP/2 sebagai penstriman pelayan → aplikasi mungkin masih membina keseluruhan badan respons → periksa timbunan pelayan API dan laluan penulisan.
  • Membenarkan penimbalan tanpa had untuk klien yang perlahan → sambungan perlahan yang serentak meningkatkan penggunaan memori → hadkan sambungan, pembatalan, dan tekanan balik.
  • Mengubah bentuk LIST atau versi sumber → klien dan semantik ketekalan akan rosak → gantikan jangka hayat pengekodan sahaja dan jalankan regresi wayar.

Soalan susulan dan jawapan

Apakah yang berlaku apabila klien terputus sambungan selepas objek ke-3,000?

Batalkan konteks pengekodan, berhenti membaca objek seterusnya, lepaskan penimbal semasa, dan rekod sebabnya. Klien tidak boleh menganggap badan separa sebagai LIST yang berjaya; ia perlu memulakan semula dari sempadan penomboran halaman asal jika ia memerlukan set penuh.

Jika penomboran halaman mengehadkan satu halaman kepada 500 objek, mengapa perlu menstrimkannya juga?

Lima ratus objek masih boleh bersaiz besar, terutamanya sumber tersuai. Penomboran halaman mengehadkan set hasil; penstriman mengehadkan memori pelayan sementara semasa pengekodan. Kedua-duanya menangani peringkat yang berbeza dan boleh digabungkan.

Adakah reka bentuk ini gagal jika proksi menimbal respons sepenuhnya sebelum memajukannya?

Pelayan masih boleh mengurangkan lonjakan pengekodannya sendiri, tetapi bait pertama klien dan faedah pelepasan hujung-ke-hujung akan hilang. Anggap penimbalan proksi sebagai prasyarat penempatan, rekod masa bait pertama mengikut laluan, dan nyahdayakan atau sempitkan ujian kenari apabila proksi tidak boleh menstrim.

Sumber awam

Soalan berkaitan

Alat temu duga berkaitan

Gunakan Jawab untuk jawapan reka bentuk sistem

Jelaskan keperluan terlebih dahulu, kemudian teruskan dengan skala, seni bina, pilihan komponen dan pertukaran (trade-off).

Lihat alat