Kehendak soalan dan skop
Reka bentuk kolam pekerja (worker pool) untuk perkhidmatan backend yang menerima tugas (job), menjalankan paling banyak sejumlah tugas tetap secara serentak (konkuren), dan ditutup tanpa menggugurkan kerja yang telah diterima secara senyap. Terangkan kapasiti giliran, penerimaan atau penolakan, pembatalan, pemilikan percubaan semula, korelasi hasil, metrik, dan penutupan tertib.
Andaikan tugas adalah bebas dan boleh memanggil API hiliran (downstream). Kolam ini ialah komponen dalam proses (in-process); giliran tahan lama (durable queues) tergolong dalam reka bentuk berasingan apabila tugas mesti bertahan daripada kegagalan proses.
Perkara yang diuji oleh penemu duga
Mereka ingin melihat had konkurensi yang jelas, model memori terhad, dan dasar untuk beban lampau (overload). Mereka juga menguji sama ada pembatalan sampai kepada pekerja, sama ada percubaan semula boleh menggandakan beban, dan sama ada penutupan membezakan tugas yang beratur, sedang berjalan, selesai, dan ditolak.
Soalan untuk dijelaskan sebelum menjawab
- Adakah kehilangan kerja semasa proses terhempas (crash) boleh diterima? Jika tidak, letakkan tugas dalam broker tahan lama terlebih dahulu.
- Adakah tugas bersifat idempoten, dan bolehkah ia dicuba semula dengan selamat?
- Apakah had kadar (rate limits) hiliran, purata masa larian, dan sasaran kependaman ekor (tail latency)?
- Patutkah serahan (submit) menyekat seketika, mengembalikan
429, atau menyingkirkan (shed) kerja berkeutamaan rendah apabila giliran penuh? - Adakah pembatalan bermaksud "berhenti sebelum mula" sahaja, atau adakah tugas boleh mengganggu I/O secara kooperatif?
Rangka jawapan 30 saat
"Saya akan menyediakan API serahan terhad yang disokong oleh bilangan pekerja tetap dan giliran terhad. Penerimaan mengembalikan hasil beban lampau yang jelas apabila kapasiti habis, manakala konteks atau token pembatalan membolehkan tugas dalam giliran keluar sebelum pelaksanaan dan membolehkan tugas yang sedang berjalan berhenti secara kooperatif. Setiap tugas yang diterima mempunyai ID dan keadaan terminal; percubaan semula dihadkan, ditambah jitter, dan dimiliki oleh satu lapisan sahaja. Metrik merangkumi kedalaman giliran, usia giliran, pekerja aktif, penolakan, masa larian, dan pembatalan. Penutupan menghentikan penerimaan, membatalkan kerja dalam giliran mengikut dasar, mengalirkan (drain) kerja yang diterima sehingga tarikh akhir (deadline), dan melaporkan apa-apa yang tidak dapat diselesaikan."
Pecahan langkah demi langkah
Langkah 1: Tentukan mesin keadaan (state machine)
Gunakan submitted → queued → running → succeeded|failed|cancelled. Giliran yang penuh menghasilkan rejected dan bukannya menunggu tanpa kepastian. Mengekalkan keadaan ini di luar proses diperlukan apabila pemanggil memerlukan pemulihan selepas ranap sistem.
Langkah 2: Hadkan kedua-dua pekerja dan giliran
Pilih W pekerja dan kapasiti giliran Q; memori dihadkan oleh Q muatan tugas ditambah tindanan pekerja. Jangan cipta satu bebenang (thread) atau goroutine bagi setiap permintaan. ThreadPoolExecutor milik Python mendedahkan max_workers, tetapi dasar penerimaan terhad peringkat aplikasi masih diperlukan apabila volum serahan tidak terhad.
Langkah 3: Pilih penerimaan dan tekanan balik (backpressure)
Tawarkan serahan tidak menyekat (non-blocking), menunggu terhad, atau penolakan berasaskan keutamaan. Kembalikan kod beban lampau yang stabil dan Retry-After hanya apabila mencuba semula adalah selamat. Pengeluar yang menunggu selama-lamanya pada giliran penuh boleh menyebabkan jalan buntu (deadlock) pada laluan permintaan, manakala giliran tanpa had menukar beban lampau kepada peningkatan kependaman dan memori.
submit(job, deadline):
if stopping or deadline expired: return REJECTED
if queue.try_push(job): return ACCEPTED(job.id)
if policy == WAIT and wait_until(deadline) and queue.try_push(job):
return ACCEPTED(job.id)
return OVERLOADEDLangkah 4: Jadikan pembatalan secara kooperatif
Sampaikan konteks pembatalan kepada setiap tugas. Alih keluar tugas yang dibatalkan yang belum dimulakan; tugas yang sedang berjalan mesti menyemak pembatalan pada titik selamat dan menyampaikannya kepada klien hiliran. Kolam tidak boleh mematikan sebarang bebenang secara selamat sewenang-wenangnya, jadi dokumentasikan maksud "dibatalkan" bagi I/O yang tidak boleh diganggu.
Langkah 5: Kekalkan pemilikan percubaan semula pada satu lapisan
Pilih sama ada kolam, pengendali tugas, atau giliran tahan lama untuk menjadualkan percubaan semula. Hadkan percubaan, tambah undur eksponen (exponential backoff) dengan jitter, dan kelaskan ralat kepada yang boleh dicuba semula dan yang kekal. Jika tidak, tamat masa (timeout) pada tiga lapisan boleh mewujudkan ribut percubaan semula (retry storm) terhadap kebergantungan yang sama.
Langkah 6: Korelasikan hasil dan ralat
Kembalikan ID tugas atau future, jangan sesekali berkongsi slot hasil boleh ubah (mutable). Rekod ralat asal, kiraan percubaan, dan keadaan terminal. Jika pemanggil melakukan pengundian (polling), jelaskan pengekalan dan kebenaran stor hasil; jika pemanggil menunggu (await), tentukan bagaimana pemutusan sambungan mempengaruhi kerja.
Langkah 7: Reka bentuk penutupan tertib (graceful shutdown)
Semasa penutupan, hentikan penerimaan terlebih dahulu, kemudian tandakan tugas dalam giliran mengikut dasar, dan biarkan tugas yang sedang berjalan mengalir sehingga tarikh akhir. Panduan saluran paip Go menyebarkan pembatalan melalui isyarat done; prinsip yang sama terpakai di sini. Selepas tarikh akhir, laporkan tugas yang belum selesai untuk dimainkan semula (replay) atau tandakannya sebagai ditinggalkan hanya dengan kontrak yang jelas.
Langkah 8: Pantau kekangan (bottleneck) dengan instrumentasi
Jejak kedalaman dan usia giliran, pekerja aktif, penggunaan, kiraan diterima/ditolak/dibatalkan, tempoh pelaksanaan, kiraan percubaan semula, dan ralat hiliran. Berikan amaran tentang usia giliran dan penolakan yang berterusan, bukan CPU sahaja. Saizkan W daripada kekangan hiliran: kolam sambungan, had kadar luaran, atau kapasiti CPU.
Pertukaran (Trade-offs) dan sempadan
Pertukaran 1: Pekerja tetap atau penskalaan dinamik
Pekerja tetap menjadikan konkurensi boleh diramal dan melindungi kebergantungan. Penskalaan dinamik boleh meningkatkan daya pemprosesan (throughput) tetapi mesti menguatkuasakan had global yang ketat dan mengambil kira setiap replika; jika tidak, setiap tika (instance) berskala secara bebas dan membebankan kebergantungan.
Pertukaran 2: Tolak atau tunggu apabila penuh
Menolak memberi maklum balas pantas kepada pemanggil dan memelihara kependaman. Menunggu boleh melicinkan lonjakan beban sementara, tetapi menunggu mesti mempunyai tarikh akhir dan tidak boleh memegang bebenang permintaan yang terhad selama-lamanya.
Pertukaran 3: Giliran dalam proses atau tahan lama
Kolam dalam proses mempunyai kependaman rendah dan mudah. Broker tahan lama menambah pemulihan, main semula, dan kos operasi. Gunakan pilihan tahan lama apabila kerja yang diterima mesti bertahan semasa deploy, ranap sistem, atau penghalaan berbilang tika.
Latih tubi kegagalan dan pelan evolusi
Latih tubi 1: Gangguan perkhidmatan hiliran
Jadikan setiap tugas gagal secara perlahan dan sahkan usia giliran, penolakan, tamat masa, dan percubaan semula yang dihadkan. Sahkan bahawa kolam tidak mencipta lebih banyak konkurensi semasa kebergantungan tidak sihat.
Latih tubi 2: Ribut pembatalan
Serahkan 10,000 tugas, batalkan separuh sebelum pelaksanaan, dan hentikan perkhidmatan semasa pengaliran (drain). Sahkan bahawa pembatalan dalam giliran tidak berjalan dan tugas berjalan yang diterima mencapai keadaan terminal yang dilaporkan.
Latih tubi 3: Pelancaran replika
Jalankan dua versi semasa rolling deploy. Periksa bahawa setiap tika menguatkuasakan had tempatannya dan bahawa giliran tahan lama atau pengehad global menguatkuasakan had seluruh sistem apabila diperlukan.
Kesilapan lazim dan tindakan susulan
Kesilapan 1: Penimbalan tanpa had
Giliran tanpa had menyembunyikan beban lampau sehingga memori atau kependaman lumpuh. Jadikan kapasiti dan dasar penolakan boleh diperhatikan (observable).
Kesilapan 2: Percubaan semula pendua
Jika kedua-dua klien HTTP dan pengendali tugas mencuba semula, percubaan akan berganda. Tetapkan satu pemilik percubaan semula dan sebarkan metadata percubaan.
Kesilapan 3: Menganggap pembatalan sebagai mematikan bebenang
Kebanyakan persekitaran masa jalan (runtime) tidak boleh mematikan kerja secara sewenang-wenangnya dengan selamat. Gunakan pemeriksaan kooperatif, I/O yang boleh dibatalkan, dan dasar kerja ditinggalkan yang jelas.
Kesilapan 4: Mengalirkan kerja tanpa menghentikan penerimaan
Tugas baharu boleh menyebabkan giliran sentiasa tidak kosong. Tutup penerimaan sebelum menunggu tarikh akhir pengaliran (drain deadline).
Kesilapan 5: Terlepas pandang had setiap replika
Kolam 20 pekerja pada 10 replika bermakna 200 panggilan serentak. Nyatakan sama ada had tersebut adalah tempatan, dipecahkan (sharded), atau diselaraskan secara global.
Kesilapan 6: Tiada dasar pengekalan hasil
Future dan rekod pengundian memerlukan tempoh luput, kebenaran, dan laluan kegagalan. Jika tidak, tugas yang diterima akan menjadi storan tanpa had.