javascript - Bagaimana Nodejs melakukan I/O di bawah hud?


Saya tahu bahawa nodejs menggunakan kolam benang yang disediakan oleh libuv untuk melakukan pekerjaan serentak. Saya membaca bahawa nodejs hanya memerlukan salah satu daripada benang itu untuk melakukan semua aktiviti terikat i/o

Jadi bagaimana operasi fail tidak menyekat berlaku?

Apa yang sebenarnya akan berlaku di belakang tabir antara node, cakera, dan OS, jika saya mengulang folder yang mengandungi 100 fail dan membuka semua menggunakan readFile()?

Jika melakukan operasi yang sama ini dalam sesetengah bahasa berbilang utas dan menyekat akan menyebabkan utas menunggu i/o selesai, maka siapa yang menunggu i/o selesai dalam nodejs?, terutamanya apabila terdapat pelbagai operasi fail yang berlaku secara serentak?

Terima kasih!

Jawapan #1

IO fail dalam nodejs menggunakan kolam benang. Secara lalai, terdapat 4 benang dalam kolam itu.

Apabila sebahagian Javascript memanggil operasi fail seperti fs.open() dalam nodejs, panggilan itu dihantar ke kod asli tertentu dalam perpustakaan libuv dalam pelaksanaan nodejs. Kod itu menambahkan operasi fail tertentu ke dalam barisan item yang menunggu untuk dijalankan oleh benang OS. Jika benang OS segera tersedia, maka benang OS itu diberikan tugas untuk menjalankan operasi fail tersebut dan kemudian fungsi libuv asal akan kembali yang seterusnya kembali ke Javascript asal dan nodejs meneruskan menjalankan Javascript lain.

Kemudian, beberapa ketika kemudian thread menyelesaikan operasi fail dan mempunyai hasil. Ia memasukkan satu acara ke dalam barisan acara nodejs dengan hasil yang lengkap dan panggilan balik asal yang dihantar bersama operasi fail asal.

Apabila Node.js telah selesai menjalankan mana-mana Javascript lain yang sedang dijalankannya, ia menarik acara seterusnya daripada barisan acara dan memanggil callback Javascript yang berkaitan dengan acara itu serta menyampaikannya data yang berkaitan dengan acara tersebut. Ini mencetuskan callback Javascript yang asalnya diberikan kepada fs.open() untuk dipanggil.

Jika, dalam langkah kedua di atas, tiada benang yang tersedia dalam kolam benang, maka tugas akan ditambahkan ke dalam barisan dan libuv segera mengembalikan kawalan kembali ke nodejs supaya ia boleh menjalankan Javascript yang lain. Beberapa ketika kemudian apabila salah satu benang yang sedia ada dalam kolam selesai dan menyiapkan kerjanya menambahkan acara ke dalam barisan acara, maka ia akan mengambil item seterusnya dari barisan kolam benang, memberikannya benang yang kini tersedia dan membiarkannya mula menjalankan operasinya.

Dengan cara ini, semua operasi fail kelihatan seperti tidak menyekat dan asinkron dari sisi Javascript. Mereka sama ada akan bermula segera jika terdapat benang yang tersedia dalam kolam benang atau mereka akan duduk dalam barisan kolam benang sehingga benang tersedia. Bahagian itu tidak kelihatan dari sisi Javascript. Bagaimanapun, operasi itu dimulakan atau ditempatkan dalam barisan dan kawalan segera kembali ke nodejs untuk terus menjalankan Javascript yang lain. Dan, bagaimanapun, operasi itu selesai kemudian dan panggilan balik Javascript yang berkaitan dengan operasi fail dipanggil melalui barisan acara Javascript. Ini menyediakan mekanisme asinkron, tidak menyekat, dan dipacu acara yang digunakan oleh nodejs untuk semua I/O fail.