Gesaan dan konteks
Perkhidmatan tak segerak (async) sering memenuhi permintaan daripada cache dalam memori tanpa melakukan I/O, namun setiap coroutine masih menjadi tugasan dan menunggu penjadualan gelung peristiwa (event-loop). Pasukan mencadangkan untuk menetapkan asyncio.eager_task_factory secara global. Nilaikan kompromi tersebut dan cadangkan rollout yang selamat.
Dokumentasi Python menyatakan bahawa pelaksanaan eager memulakan coroutine secara segerak semasa Task dibina; Task hanya dijadualkan apabila coroutine menyekat (blocks). API ini ditambah dalam Python 3.12 dan mengubah semantik penjadualan yang boleh diperhatikan.
Perkara yang diuji oleh penemuduga
Kuncinya adalah membezakan penyiapan segerak daripada penyekatan tak segerak serta menerangkan kesannya terhadap keadilan (fairness), susunan, pemasaan pengecualian, pembatalan dan TaskGroup. Jawapan yang kukuh mengehadkan pengoptimuman kepada sempadan yang diukur dan merangkumi semakan versi, feature flag, rollback dan metrik event-loop.
Soalan penjelasan untuk ditanya terlebih dahulu
- Apakah versi Python minimum merentas setiap pelaksanaan (deployment)?
- Adakah coroutine ini membaca memory-cache, atau bolehkah ia melakukan I/O rangkaian, pangkalan data, fail, atau kunci (lock)?
- Adakah kod bergantung pada susunan penciptaan tugasan, keadilan gelung, atau susunan
call_soon? - Adakah kegagalan, pembatalan, dan tarikh akhir (deadlines) dimiliki oleh
TaskGroupatau skop permintaan? - Adakah sasarannya CPU penciptaan tugasan, latensi ekor (tail latency), atau pemprosesan (throughput), dan apakah garis dasarnya (baseline)?
Rangka kerja jawapan 30 saat
“Saya tidak akan mendayakannya secara global terlebih dahulu. Eager factory memulakan coroutine semasa pembinaan Task, jadi hit cache boleh mengelakkan satu giliran penjadualan event-loop; coroutine yang menyekat dijadualkan seperti biasa. Ini mengubah susunan, pemasaan pengecualian dan keadilan: gelung yang mencipta banyak tugasan segerak boleh melengahkan pemasa dan permintaan lain. Saya akan menyemak versi Python, melancarkannya di tapak panggilan cache yang diukur, membandingkan lag event-loop dan latensi ekor, serta mengekalkan kilang lalai sebagai rollback serta-merta.”
Penerokaan mendalam langkah demi langkah
Langkah 1: Nyatakan model lalai dan eager
Dengan kilang lalai, create_task menjadualkan coroutine untuk berjalan tidak lama lagi. Dengan eager factory, pembinaan memajukannya serta-merta sehingga ia kembali, menimbulkan pengecualian, atau mencapai await penyekat pertamanya. Penyiapan segerak mungkin tidak akan pernah memasuki barisan gilir event-loop.
loop.set_task_factory(asyncio.eager_task_factory)
task = asyncio.create_task(read_cached(key))Oleh itu, pelaksanaan eager ialah perubahan semantik yang boleh diperhatikan, bukan sekadar penjadual yang lebih pantas.
Langkah 2: Pilih sempadan coroutine
Calon yang baik ialah operasi memory-cache atau memoized yang singkat dan mempunyai kadar hit yang tinggi. Coroutine yang mungkin melakukan kerja rangkaian, pangkalan data, fail, kunci, atau CPU tanpa batas harus mengekalkan sempadan penyekatan yang boleh diramal supaya pembinaan tidak memonopoli tugasan semasa.
Langkah 3: Analisis susunan dan keadilan
Apabila tugasan dicipta dalam gelung, eager coroutine boleh selesai serta-merta mengikut susunan penciptaan, mengubah selang-seli yang sebelum ini bergantung pada event loop. Kumpulan (batch) segerak yang besar boleh melengahkan pemasa, panggilan balik I/O dan permintaan lain. Jejaki lag event-loop dan hadkan saiz batch.
Langkah 4: Kendalikan pengecualian dan pembatalan
Pengecualian yang ditimbulkan sebelum sekatan pertama boleh muncul berhampiran create_task, mengubah titik tangkapan dan bentuk tindanan (stack). Simpan rujukan Task, dan biarkan CancelledError merambat selepas pembersihan. Jangan sekali-kali menggunakan mod eager untuk mengubah pembatalan permintaan atau kegagalan cache menjadi respons yang berjaya.
Langkah 5: Gabungkannya dengan TaskGroup dan tarikh akhir
TaskGroup masih memiliki pepohon tugasan, pembatalan rakan sekelompok (sibling), dan gabungan (join), tetapi anak mungkin telah selesai atau gagal semasa create_task. Gunakan pengendalian try/except* berstruktur dan satu tarikh akhir luaran; jangan anggap setiap anak menunggu dalam barisan gilir terlebih dahulu.
async with asyncio.TaskGroup() as group:
user = group.create_task(read_cached("user"))
orders = group.create_task(read_remote("orders"))Langkah 6: Semak versi dan skopkan ciri
Kilang ini tersedia bermula dari Python 3.12. Python 3.14 juga mendedahkan pilihan eager_start pada create_task. Perkhidmatan pelbagai versi harus mengesahkan masa larian (runtime) semasa permulaan dan mengutamakan eksperimen tapak panggilan tempatan berbanding perubahan kilang global tanpa syarat.
Langkah 7: Lancarkan dengan metrik rollback
Mulakan di tapak panggilan cache sahaja di sebalik suis. Bandingkan CPU, masa pembinaan tugasan, latensi ekor hit cache, lag event-loop, kadar pengecualian, kadar pembatalan dan QPS hiliran berbanding kilang lalai. Jika keadilan atau ralat merosot, pulihkan lalai tanpa mengubah kod perniagaan.
Langkah 8: Uji semantik, bukan hanya penanda aras
Liputi pulangan segerak, peningkatan pengecualian segerak, await pertama, pembatalan luaran, pelbagai kegagalan TaskGroup, tarikh akhir, penciptaan tugasan rekursif, keadilan pemasa, dan batch campuran cache/jauh. Rakam peristiwa dan sahkan susunan; penanda aras throughput sahaja tidak dapat mengesahkan semantik penjadualan.
Model jawapan berkualiti tinggi
“Pelaksanaan eager sesuai untuk coroutine cache yang singkat dan boleh diramal kerana ia menghapuskan satu giliran penjadualan; ia berisiko untuk I/O yang tidak dapat diramalkan atau laluan CPU yang panjang. Risiko utama ialah perubahan susunan, keadilan dan pemasaan pengecualian. Saya akan menyemak versi, mendayakannya secara tempatan di sebalik bendera, mengekalkan rollback lalai, dan memantau lag event-loop, latensi ekor, pembatalan dan ralat. TaskGroup dan tarikh akhir bersama kekal digunakan, begitu juga pembatalan dan pembersihan normal.”
Kesilapan biasa
- Menganggap mod eager bebas semantik → susunan dan pemasaan pengecualian berubah → tuliskan kedua-dua model pelaksanaan dan ukur.
- Mendayakannya untuk setiap coroutine → I/O atau CPU yang perlahan menyekat tugasan semasa → lakukan ujian kenari (canary) hanya pada laluan segerak yang pendek.
- Mengabaikan versi Python → deployment yang lebih lama gagal semasa permulaan → sahkan runtime dan kekalkan kilang lalai.
- Hanya melihat throughput purata → keadilan merosot secara senyap → tambah metrik lag gelung dan ekor.
- Menganggap TaskGroup tidak berubah → kegagalan masa pembinaan disalah kendali → uji kegagalan anak eager dan kumpulan pengecualian.
- Menelan ralat pembatalan atau pembersihan → permintaan membocorkan kerja → pelihara pembatalan dan sahkan laluan pelepasan.
Soalan susulan dan respons yang mantap
Susulan 1: Adakah hit cache segerak masih meninggalkan Task?
Task mungkin sudah selesai semasa pembinaan. Jangan memerlukan giliran event-loop; baca objek yang dikembalikan dan uji laluan penyiapan eager secara eksplisit.
Susulan 2: Adakah mod eager menjamin susunan penciptaan untuk penyiapan?
Tidak. Ia hanya mengubah masa mula; sebaik sahaja coroutine menyekat, penjadualan normal diguna pakai. Jika susunan perniagaan penting, selaraskan secara eksplisit atau susun keputusan mengikut kunci operasi.
Susulan 3: Bagaimanakah anda menghalang batch hit cache daripada menjejaskan permintaan lain (starvation)?
Hadkan batch, serahkan kawalan (yield) antara batch apabila sesuai, dan perhatikan lag gelung. Menggunakan mod eager pada satu tapak panggilan berkos rendah adalah lebih selamat daripada dasar global.
Susulan 4: Bagaimanakah anda mengundurkannya (rollback) selepas regresi berlaku?
Nyahdayakan suis, pulihkan kilang tugasan lalai, sahkan metrik kembali kepada garis dasar, dan kekalkan jejak yang mengandungi versi runtime dan susunan peristiwa untuk diagnosis.
Susulan 5: Bagaimanakah eager_start berkaitan dengan kilang tersebut?
eager_start ialah pilihan eksplisit untuk satu Task; kilang ialah dasar lalai event-loop. Sahkan tandatangan versi Python dan keutamaan yang tepat sebelum menggabungkannya.