Saya telah membaca kode sumber node.js & v8 secara pribadi.
Saya mengalami masalah yang sama seperti Anda ketika saya mencoba memahami arsitektur node.js untuk menulis modul asli.
Apa yang saya posting di sini adalah pemahaman saya tentang node.js dan ini mungkin agak keluar jalur juga.
Libev adalah loop peristiwa yang sebenarnya berjalan secara internal di node.js untuk melakukan operasi loop peristiwa sederhana. Ini awalnya ditulis untuk sistem * nix. Libev menyediakan loop acara sederhana namun dioptimalkan untuk menjalankan proses. Anda dapat membaca lebih lanjut tentang libev sini .
LibEio adalah pustaka untuk melakukan output input secara tidak sinkron. Ini menangani deskriptor file, penangan data, soket dll. Anda dapat membaca lebih lanjut di sini sini sini .
LibUv adalah lapisan abstraksi di atas libeio, libev, c-ares (untuk DNS) dan iocp (untuk windows asynchronous-io). LibUv melakukan, mengelola, dan mengelola semua io dan acara di kumpulan acara. (dalam hal libeio threadpool). Anda harus memeriksa tutorial Ryan Dahl tentang libUv. Itu akan mulai lebih masuk akal bagi Anda tentang bagaimana libUv bekerja dengan sendirinya dan kemudian Anda akan memahami bagaimana node.js bekerja di atas libuv dan v8.
Untuk memahami hanya loop acara javascript Anda harus mempertimbangkan menonton video ini
Untuk melihat bagaimana libeio digunakan dengan node.js untuk membuat modul async, Anda harus melihatnya contoh ini .
Pada dasarnya apa yang terjadi di dalam node.js adalah bahwa v8 loop berjalan dan menangani semua bagian javascript serta modul C ++ [ketika mereka berjalan di utas utama (sesuai dokumentasi resmi, node.js sendiri berulir tunggal)]. Saat berada di luar utas utama, libev dan libeio menanganinya di kumpulan utas dan libev memberikan interaksi dengan loop utama. Jadi dari pemahaman saya, node.js memiliki 1 loop acara permanen: itulah loop acara v8. Untuk menangani tugas async C ++ itu menggunakan threadpool [via libeio & libev].
Sebagai contoh:
eio_custom(Task,FLAG,AfterTask,Eio_REQUEST);
Yang muncul di semua modul biasanya memanggil fungsi Task
di threadpool. Setelah selesai, ia memanggil AfterTask
fungsi di utas utama. Sedangkan Eio_REQUEST
request handler yang dapat berupa struktur / objek yang motifnya adalah untuk menyediakan komunikasi antara threadpool dan utas utama.
process.nextTick
- Pada loop berikutnya di sekitar loop acara panggil panggilan balik ini. Ini bukan alias sederhana untuk setTimeout (fn, 0), ini jauh lebih efisien. Perulangan acara apa yang dirujuk oleh ini? V8 event loop?Sepertinya beberapa entitas yang dibahas (misalnya: libev dll.) Telah kehilangan relevansinya, karena faktanya sudah lama, tapi saya pikir pertanyaannya masih memiliki potensi besar.
Izinkan saya mencoba menjelaskan cara kerja model yang didorong oleh peristiwa dengan bantuan contoh abstrak, dalam lingkungan UNIX yang abstrak, dalam konteks Node, hingga hari ini.
Perspektif program:
Mesin acara di atas disebut kerangka kerja libuv AKA event loop. Node memanfaatkan pustaka ini untuk mengimplementasikan model pemrograman yang didorong oleh peristiwa.
Perspektif Node:
Sementara sebagian besar fungsi dipenuhi dengan cara ini, beberapa (versi async) operasi file dilakukan dengan bantuan utas tambahan, terintegrasi dengan baik ke dalam libuv. Sementara operasi jaringan I / O dapat menunggu dengan harapan peristiwa eksternal seperti titik akhir lainnya merespons dengan data dll. Operasi file memerlukan beberapa pekerjaan dari node itu sendiri. Misalnya, jika Anda membuka file dan menunggu fd siap dengan data, itu tidak akan terjadi, karena tidak ada yang membaca sebenarnya! Pada saat yang sama, jika Anda membaca dari file inline di utas utama, ini berpotensi memblokir aktivitas lain dalam program, dan dapat membuat masalah yang terlihat, karena operasi file sangat lambat dibandingkan dengan aktivitas cpu terikat. Jadi utas pekerja internal (dapat dikonfigurasi melalui variabel lingkungan UV_THREADPOOL_SIZE) digunakan untuk beroperasi pada file,
Semoga ini membantu.
sumber
Pengantar libuv
Juga satu gambar yang menggambarkan Event Loop di Node.js oleh @ BusyRich
Perbarui 05/09/2017
Per loop acara Node.js doc ini ,
Diagram berikut menunjukkan ikhtisar yang disederhanakan dari urutan operasi loop acara.
catatan: setiap kotak akan disebut sebagai "fase" dari loop acara.
Ikhtisar Fase
setTimeout()
dansetInterval()
.setImmediate()
.setImmediate()
callback dipanggil di sini.socket.on('close', ...)
.Di antara setiap putaran acara, Node.js memeriksa apakah menunggu I / O atau timer tidak sinkron dan dimatikan dengan bersih jika tidak ada.
sumber
In the node-v0.9.0 version of libuv libev was removed
", tetapi tidak ada deskripsi tentang hal itu di nodejschangelog
. github.com/nodejs/node/blob/master/CHANGELOG.md . Dan jika libev dihapus maka sekarang bagaimana async I / O dilakukan di nodejs?Ada satu loop acara di Arsitektur NodeJs.
Model Loop Acara Node.js
Aplikasi Node berjalan dalam model event-driven single-threaded. Namun, Node mengimplementasikan kumpulan utas di latar belakang sehingga pekerjaan dapat dilakukan.
Node.js menambahkan pekerjaan ke antrian acara dan kemudian memiliki utas tunggal menjalankan perulangan acara. Perulangan acara mengambil item teratas dalam antrian acara, mengeksekusi, dan lalu mengambil item berikutnya.
Ketika mengeksekusi kode yang berumur panjang atau memblokir I / O, alih-alih memanggil fungsi secara langsung, ia menambahkan fungsi ke antrian acara bersama dengan callback yang akan dieksekusi setelah fungsi selesai. Ketika semua peristiwa di antrian acara Node.js telah dieksekusi, aplikasi Node.js berakhir.
Perulangan acara mulai menimbulkan masalah saat fungsi aplikasi kami memblokir pada I / O.
Node.js menggunakan event callback untuk menghindari keharusan menunggu pemblokiran I / O. Oleh karena itu, setiap permintaan yang melakukan pemblokiran I / O dilakukan pada utas yang berbeda di latar belakang.
Ketika acara yang memblokir I / O diambil dari antrian acara, Node.js mengambil utas dari kumpulan utas, dan menjalankan fungsi di sana alih-alih pada utas loop acara utama. Ini mencegah I / O pemblokiran menahan sisa acara dalam antrian acara.
sumber
Hanya ada satu loop acara yang disediakan oleh libuv, V8 hanyalah mesin runtime JS.
sumber
Sebagai pemula javascript, saya juga memiliki keraguan yang sama, apakah NodeJS berisi 2 loop peristiwa ?. Setelah riset panjang dan berdiskusi dengan salah satu kontributor V8, saya mendapat konsep berikut.
sumber
The
pbkdf2
fungsi memiliki implementasi JavaScript tetapi sebenarnya delegasi semua pekerjaan yang harus dilakukan untuk C ++ sisi.sumber daya: https://github.com/nodejs/node/blob/master/src/node_crypto.cc
Modul Libuv memiliki tanggung jawab lain yang relevan untuk beberapa fungsi yang sangat khusus di perpustakaan standar.
Untuk beberapa panggilan fungsi pustaka standar, sisi Node C ++ dan Libuv memutuskan untuk melakukan perhitungan mahal di luar loop acara sepenuhnya.
Alih-alih mereka menggunakan sesuatu yang disebut kolam ulir, kolam ulir adalah serangkaian empat utas yang dapat digunakan untuk menjalankan tugas yang mahal secara komputasi seperti
pbkdf2
fungsi.Secara default Libuv membuat 4 utas di kumpulan utas ini.
Selain utas yang digunakan dalam event loop ada empat utas lain yang dapat digunakan untuk membongkar perhitungan mahal yang perlu terjadi di dalam aplikasi kita.
Banyak fungsi yang disertakan dalam pustaka Node standar secara otomatis memanfaatkan kumpulan utas ini. The
pbkdf2
fungsi menjadi salah satu dari mereka.Kehadiran kumpulan utas ini sangat signifikan.
Jadi Node tidak benar-benar satu threaded, karena ada thread lain yang digunakan Node untuk melakukan beberapa tugas yang mahal secara komputasi.
Jika kumpulan acara bertanggung jawab untuk melakukan tugas yang mahal secara komputasi, maka aplikasi Node kami tidak dapat melakukan hal lain.
CPU kami menjalankan semua instruksi di dalam utas satu per satu.
Dengan menggunakan kumpulan utas kita dapat melakukan hal-hal lain di dalam perulangan peristiwa saat perhitungan terjadi.
sumber