Rumah >hujung hadapan web >tutorial js >Node.js asynchronous I/O study note_node.js

Node.js asynchronous I/O study note_node.js

WBOY
WBOYasal
2016-05-16 16:32:051203semak imbas

Istilah "tak segerak" menjadi popular secara meluas dalam gelombang Web 2.0, yang menyapu Web bersama-sama dengan Javascript dan AJAX. Tetapi dalam kebanyakan bahasa pengaturcaraan peringkat tinggi, asynchrony jarang berlaku. PHP merangkumi ciri ini: ia bukan sahaja menyekat asynchronous, malah tidak menyediakan berbilang benang PHP dilaksanakan dengan cara menyekat segerak. Kelebihan ini membantu pengaturcara menulis logik perniagaan secara berurutan, tetapi dalam aplikasi rangkaian yang kompleks, penyekatan menghalang keselarasan yang lebih baik.

Di bahagian pelayan, I/O adalah sangat mahal, dan I/O yang diedarkan adalah lebih mahal Hanya apabila bahagian belakang boleh bertindak balas kepada sumber dengan cepat, pengalaman bahagian hadapan boleh menjadi lebih baik. Node.js ialah platform pertama yang menggunakan asynchronous sebagai kaedah pengaturcaraan utama dan konsep reka bentuk Bersama-sama dengan I/O asynchronous, terdapat event-driven dan single-threaded, yang membentuk nada Node. Artikel ini akan memperkenalkan cara Node melaksanakan I/O tak segerak.

1. Konsep asas

"Asynchronous" dan "non-blocking" berbunyi seperti perkara yang sama Dari segi kesan praktikal, kedua-duanya mencapai tujuan paralelisme. Tetapi dari perspektif I/O kernel komputer, hanya terdapat dua kaedah: menyekat dan tidak menyekat. Jadi asynchronous/synchronous dan blocking/non-blocking sebenarnya adalah dua perkara yang berbeza.

1.1 Menyekat I/O dan I/O tidak menyekat

Satu ciri menyekat I/O ialah selepas panggilan, panggilan mesti menunggu sehingga semua operasi selesai di peringkat kernel sistem sebelum panggilan tamat. Mengambil membaca fail pada cakera sebagai contoh, panggilan ini tamat selepas kernel sistem melengkapkan pencarian cakera, membaca data dan menyalin data ke memori.

Menyekat I/O menyebabkan CPU menunggu I/O, membuang masa menunggu dan kuasa pemprosesan CPU tidak dapat digunakan sepenuhnya. Ciri I/O tidak menyekat ialah ia kembali serta-merta selepas panggilan Selepas pemulangan, potongan masa CPU boleh digunakan untuk memproses transaksi lain. Memandangkan I/O lengkap belum selesai, apa yang dikembalikan serta-merta bukanlah data yang dijangkakan oleh lapisan perniagaan, tetapi hanya status panggilan semasa. Untuk mendapatkan data yang lengkap, aplikasi perlu berulang kali memanggil operasi I/O untuk mengesahkan sama ada ia telah selesai (iaitu pengundian). Teknik pengundian termasuk yang berikut:

1.baca: Menyemak status I/O melalui panggilan berulang ialah cara yang paling primitif dan berprestasi paling rendah
2.pilih: Penambahbaikan bacaan, berdasarkan status acara pada deskriptor fail. Kelemahannya ialah bilangan maksimum deskriptor fail adalah terhad
3. tinjauan pendapat: Penambahbaikan pilihan, menggunakan senarai terpaut untuk mengelakkan had nombor maksimum, tetapi apabila terdapat banyak deskriptor, prestasi masih sangat rendah
4.epoll: Jika tiada acara I/O dikesan semasa memasuki pengundian, ia akan tidur sehingga peristiwa berlaku untuk membangunkannya. Ini ialah mekanisme pemberitahuan acara I/O yang paling cekap pada masa ini di bawah Linux

Polling memenuhi keperluan I/O tanpa sekatan untuk memastikan pemerolehan data lengkap, tetapi untuk aplikasi, ia masih boleh dikira sebagai sejenis penyegerakan, kerana ia masih perlu menunggu I/O kembali sepenuhnya. Semasa tempoh menunggu, CPU sama ada digunakan untuk melintasi status deskriptor fail atau digunakan untuk tidur dan menunggu peristiwa berlaku.

1.2 I/O tak segerak dalam ideal dan realiti

I/O tak segerak yang sempurna sepatutnya apabila aplikasi memulakan panggilan tidak menyekat dan boleh memproses tugas seterusnya secara langsung tanpa undian Ia hanya perlu menghantar data kepada aplikasi melalui isyarat atau panggilan balik selepas I/O selesai.

I/O tak segerak pada realitinya mempunyai pelaksanaan yang berbeza di bawah sistem pengendalian yang berbeza Contohnya, platform *nix menggunakan kumpulan benang tersuai, dan platform Windows menggunakan model IOCP. Node menyediakan libuv sebagai lapisan enkapsulasi abstrak untuk merangkum pertimbangan keserasian platform dan memastikan bahawa pelaksanaan I/O tak segerak bagi Nod atas dan platform bawah adalah bebas. Di samping itu, perlu ditekankan bahawa kita sering menyebut bahawa Node adalah satu-benang Ini hanya bermakna bahawa Javascript dilaksanakan dalam satu utas Terdapat kumpulan benang yang benar-benar menyelesaikan tugasan I/O di dalam Node.

2. I/O Asynchronous Nod

Gelung Acara 2.1

Model pelaksanaan nod sebenarnya ialah gelung peristiwa. Apabila proses bermula, Node akan mencipta gelung tak terhingga, dan setiap pelaksanaan badan gelung menjadi Tick. Setiap proses Tick adalah untuk menyemak sama ada terdapat peristiwa yang menunggu untuk diproses, dan jika ya, dapatkan semula acara dan fungsi panggil balik yang berkaitan. Jika terdapat fungsi panggil balik yang berkaitan, laksanakannya, dan kemudian masukkan gelung seterusnya. Jika tiada lagi acara untuk dikendalikan, keluar daripada proses.

2.2 Pemerhati

Terdapat beberapa pemerhati dalam setiap gelung peristiwa dan anda boleh menentukan sama ada terdapat peristiwa untuk diproses dengan bertanya kepada pemerhati ini. Gelung acara ialah model pengeluar/pengguna biasa. Dalam Node, peristiwa terutamanya datang daripada permintaan rangkaian, fail I/O, dsb. Peristiwa ini mempunyai pemerhati I/O rangkaian yang sepadan, pemerhati I/O fail, dsb. Gelung peristiwa mengambil peristiwa daripada pemerhati dan memprosesnya.

2.3 Meminta objek

Dalam proses peralihan daripada Javascript yang memulakan panggilan ke kernel yang melengkapkan operasi I/O, terdapat produk perantaraan yang dipanggil objek permintaan. Mengambil kaedah fs.open() yang paling mudah di bawah Windows (untuk membuka fail dan mendapatkan deskriptor fail mengikut laluan dan parameter yang ditentukan) sebagai contoh, memanggil sistem dari JS ke modul terbina dalam melalui libuv sebenarnya memanggil uv_fs_open( ) kaedah. Semasa proses memanggil, objek permintaan FSReqWrap dibuat Parameter dan kaedah yang dihantar dari lapisan JS dirangkumkan dalam objek permintaan ini. Selepas objek dibalut, objek FSReqWrap ditolak ke dalam kumpulan benang untuk menunggu pelaksanaan.

Pada ketika ini, panggilan JS kembali serta-merta dan urutan JS boleh terus melakukan operasi seterusnya. Operasi I/O semasa sedang menunggu untuk dilaksanakan dalam kumpulan benang, yang melengkapkan fasa pertama panggilan tak segerak.

2.4 Panggil balik pelaksanaan

Pemberitahuan panggilan balik ialah fasa kedua I/O tak segerak. Selepas operasi I/O dalam kumpulan benang dipanggil, hasil yang diperoleh akan disimpan, dan kemudian IOCP akan dimaklumkan bahawa operasi objek semasa telah selesai, dan benang akan dikembalikan ke kumpulan benang. Semasa setiap pelaksanaan Tick, pemerhati I/O bagi gelung peristiwa akan memanggil kaedah yang berkaitan untuk menyemak sama ada terdapat permintaan yang lengkap dalam kumpulan benang Jika ada, objek permintaan akan ditambahkan pada baris gilir I/O pemerhati kemudian menganggapnya sebagai satu peristiwa.

3. API tak segerak Bukan I/O

Terdapat juga beberapa API tak segerak dalam Node yang tiada kaitan dengan I/O, seperti pemasa setTimeout(), setInterval(), process.nextTick() dan setImmdiate() yang melaksanakan tugas secara tidak segerak, dsb. Di sini adalah pengenalan ringkas.

API Pemasa 3.1

API sebelah penyemak imbas setTimeout() dan setInterval() adalah konsisten Prinsip pelaksanaannya adalah serupa dengan I/O tak segerak, tetapi ia tidak memerlukan penyertaan kumpulan benang I/O. Pemasa yang dibuat dengan memanggil API pemasa akan dimasukkan ke dalam pokok merah-hitam di dalam pemerhati pemasa Setiap Tick pada gelung acara akan secara berulang mengalih keluar objek pemasa daripada pokok merah-hitam dan menyemak sama ada pemasa telah melebihi Jika ia melebihi, peristiwa terbentuk, dan fungsi panggil balik dilaksanakan serta-merta. Masalah utama dengan pemasa ialah pemasaannya tidak begitu tepat (milisaat, dalam toleransi).

3.2 API pelaksanaan tugas tak segerak segera

Sebelum Node muncul, ramai orang mungkin memanggil ini untuk melaksanakan tugasan dengan segera dan tidak segerak:

Salin kod Kod adalah seperti berikut:

setTimeout(function() {
// TODO
}, 0);

Disebabkan ciri gelung acara, pemasa tidak cukup tepat dan menggunakan pemasa memerlukan penggunaan pokok merah-hitam, dan kerumitan masa pelbagai operasi ialah O(log(n)). Kaedah process.nextTick() hanya akan meletakkan fungsi panggil balik ke dalam baris gilir, dan mengeluarkannya untuk pelaksanaan dalam pusingan Tick seterusnya Kerumitannya ialah O(1), yang lebih cekap.

Terdapat juga kaedah setImmediate() yang serupa dengan kaedah di atas, yang melambatkan pelaksanaan fungsi panggil balik. Walau bagaimanapun, yang pertama mempunyai keutamaan yang lebih tinggi daripada yang kedua, kerana gelung peristiwa menyemak pemerhati mengikut tertib. Selain itu, fungsi panggil balik yang pertama disimpan dalam tatasusunan, dan setiap pusingan Tick akan melaksanakan semua fungsi panggil balik dalam tatasusunan itu disimpan dalam senarai terpaut, dan hanya satu fungsi panggil balik akan dilaksanakan setiap pusingan Tick.

4. Didorong oleh acara dan pelayan berprestasi tinggi

Contoh sebelumnya menggunakan fs.open() untuk menerangkan cara Node melaksanakan I/O tak segerak. Malah, Node juga menggunakan I/O tak segerak untuk memproses soket rangkaian, yang juga merupakan asas untuk Node membina pelayan web. Model pelayan klasik termasuk:

1. Segerak: Hanya satu permintaan boleh diproses pada satu masa, dan permintaan yang selebihnya berada dalam keadaan menunggu
2. Setiap proses/setiap permintaan: Mulakan proses untuk setiap permintaan, tetapi sumber sistem adalah terhad dan tidak boleh berskala
3. Setiap urutan/setiap permintaan: Mulakan urutan untuk setiap permintaan. Benang lebih ringan daripada proses, tetapi setiap utas menempati jumlah memori tertentu Apabila permintaan serentak yang besar tiba, memori akan digunakan dengan cepat

Apache yang terkenal menggunakan format per-thread/per-permintaan, itulah sebabnya sukar untuk mengatasi keselarasan yang tinggi. Node mengendalikan permintaan dalam cara yang didorong oleh peristiwa, yang boleh menjimatkan overhed mencipta dan memusnahkan benang Pada masa yang sama, kerana sistem pengendalian mempunyai lebih sedikit urutan semasa menjadualkan tugas, kos penukaran konteks juga sangat rendah. Node mengendalikan permintaan dengan teratur walaupun dengan bilangan sambungan yang banyak.

Pelayan terkenal Nginx juga meninggalkan kaedah berbilang benang dan menggunakan kaedah dipacu peristiwa yang sama seperti Node. Kini, Nginx mempunyai potensi besar untuk menggantikan Apache. Nginx ditulis dalam C tulen dan mempunyai prestasi tinggi, tetapi ia hanya sesuai untuk pelayan web, proksi terbalik atau pengimbangan beban, dsb. Node boleh membina fungsi yang sama seperti Nginx, juga boleh mengendalikan pelbagai perniagaan tertentu, dan prestasinya sendiri juga baik. Dalam projek sebenar, kita boleh menggabungkan kelebihan masing-masing untuk mencapai prestasi terbaik aplikasi.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn