Mari kita bincangkan tentang pelaksanaan tak segerak dan pemanduan acara dalam Node

青灯夜游
Lepaskan: 2022-11-08 20:14:44
ke hadapan
1229 orang telah melayarinya

Artikel ini akan membawa anda melalui pelaksanaan tak segerak dan pemacu acara dalam Nod Saya harap ia akan membantu anda!

Mari kita bincangkan tentang pelaksanaan tak segerak dan pemanduan acara dalam Node

Ciri Nod

Sesetengah tugasan dalam komputer secara umumnya boleh dibahagikan kepada dua kategori, satu kategori dipanggil IO Intensif, satu dipanggil intensif pengkomputeran; untuk tugas intensif pengkomputeran, prestasi CPU hanya boleh dikuras secara berterusan, tetapi untuk tugas intensif IO, idealnya ini tidak diperlukan, dan hanya peranti IO perlu dimaklumkan untuk pemprosesan . , kembali dan dapatkan data selepas beberapa ketika. [Tutorial berkaitan yang disyorkan: tutorial video nodejs, Video pengaturcaraan]

Untuk sesetengah senario, terdapat beberapa tugasan yang tidak berkaitan yang perlu diselesaikan, semasa arus perdana Terdapat dua kaedah:

  • Penyiapan selari berbilang benang: Kos berbilang benang ialah overhed tinggi untuk mencipta benang dan melaksanakan penukaran konteks benang. Di samping itu, dalam perniagaan yang kompleks, pengaturcaraan berbilang benang sering menghadapi masalah seperti kunci dan penyegerakan keadaan
  • Pelaksanaan berurutan berurutan tunggal: mudah untuk dinyatakan, tetapi kelemahan pelaksanaan bersiri adalah prestasi, dan sedikit lebih perlahan; tugas akan Akibatnya, kod berikutnya telah disusun

node dan penyelesaiannya diberikan sebelum kedua-duanya: gunakan satu utas untuk menjauhkan diri daripada masalah seperti kebuntuan berbilang benang dan penyegerakan status ; gunakan IO tak segerak untuk membenarkan satu Thread menjauhkan diri daripada menyekat untuk menggunakan CPU dengan lebih baik

Cara Node melaksanakan tak segerak

Baru dibincangkannode Dalam penyelesaian multi-tasking, tetapi node bukan mudah untuk dilaksanakan secara dalaman, berikut adalah beberapa konsep sistem pengendalian, supaya semua orang dapat memahaminya dengan lebih baik pada masa hadapan , kita akan bercakap tentang pelaksanaan tak segerak dan mekanisme gelung:

Menyekat IO dan tidak menyekat IO

  • Menyekat IO: Selepas lapisan aplikasi memulakan panggilan IO, ia terus menunggu untuk data dan operasi Panggilan tamat selepas semua operasi selesai pada peringkat kernel sistem; dan peranti input dan output juga diabstraksikan ke dalam fail Apabila kernel menjalankan operasi IO, ia melepasi
  • Deskriptor fail
untuk pengurusan

IO tidak menyekat: Perbezaannya ialah. bahawa deskriptor fail dikembalikan serta-merta selepas panggilan tanpa menunggu Pada masa ini, kepingan masa CPU boleh digunakan Selepas memproses transaksi lain, keputusan boleh diperolehi melalui deskriptor fail ini; dengan IO yang tidak menyekat: Walaupun ia meningkatkan penggunaan CPU, kerana pulangan segera ialah deskriptor Fail, kami tidak tahu bila operasi IO selesai Untuk mengesahkan perubahan status, kami hanya boleh melakukan operasi pengundian

    Kaedah pengundian yang berbeza

: Kaedah yang paling primitif dan paling rendah prestasinya, melengkapkan pemerolehan data lengkap dengan

berulang kali menyemak status IO

    : dengan menyemak
  • deskriptor fail Status acara read digunakan untuk menilai, yang secara relatifnya lebih murah ialah ia menggunakan tatasusunan 1024 panjang untuk menyimpan status, jadi ia boleh menyemak sehingga 1024 deskriptor fail pada masa yang sama
  • : Disebabkan oleh pengehadan
  • , select dipertingkatkan kepada kaedah storan senarai terpaut dan segala-galanya pada asasnya adalah sama; tetapi apabila terdapat banyak deskriptor fail, prestasinya masih sangat rendah
  • : Penyelesaian ini adalah mekanisme pemberitahuan acara IO yang paling berkesan di bawah
  • Jika tiada acara IO disemak apabila memasuki pengundian, ia akan tidur sehingga berlaku peristiwa untuk membangunkannya pollselectpoll : Serupa dengan
  • , tetapi hanya wujud di bawah sistem FreeBSD
  • eoplllinuxWalaupun
  • menggunakan peristiwa untuk mengurangkan penggunaan CPU, CPU hampir melahu semasa hibernasi; apa yang kami jangkakan IO Asynchronous harus menjadi panggilan tidak menyekat yang dimulakan oleh aplikasi Tidak perlu membuat tinjauan melalui traversal atau acara bangun diproses secara langsung Ia hanya perlu menghantar data kepada aplikasi melalui isyarat atau panggilan balik selepas IO selesai.
  • kqueueepollTerdapat juga kaedah AIO di bawah Linux yang menghantar data melalui isyarat atau panggilan balik, tetapi ia hanya tersedia di Linux, dan terdapat sekatan yang tidak boleh menggunakan cache sistem

epoll Pelaksanaan IO tak segerak dalam nod

Mari kita bincangkan tentang kesimpulan dahulu

Pelaksanaan IO tak segerak dilaksanakan melalui multi-threading. Apa yang mungkin mengelirukan ialah walaupun
berbilang benang secara dalaman, kod

yang dibangunkan oleh pengaturcara kami hanya berjalan pada satu utas.

nodeGunakan beberapa utas untuk melaksanakan menyekat IO atau tidak menyekat IO serta teknologi pengundian untuk melengkapkan pemerolehan data, biarkan satu utas melakukan pengiraan dan pemprosesan, dan memindahkan data yang diperoleh daripada IO melalui komunikasi antara utas, yang mudah Dilaksanakan simulasi IO tak segerak.

Selain IO tak segerak, sumber lain dalam komputer juga boleh digunakan, kerana segala-galanya dalam Linux adalah fail, dan hampir semua sumber komputer seperti cakera, perkakasan, dan soket disarikan fail, pengenalan seterusnya kepada panggilan ke sumber komputer mengambil IO sebagai contoh.

Gelung Acara

Apabila proses bermula, node akan mencipta gelung serupa dengan while(true) Setiap kali badan gelung dilaksanakan, kita menjadi Tick;

Di bawah ialah carta alir gelung acara dalam node:

Gambar yang sangat ringkas, penjelasan ringkas: ia bermakna setiap kali Dapatkan acara selesai daripada pemerhati IO (ia adalah objek permintaan, pemahaman mudah ialah ia mengandungi beberapa data yang dijana dalam permintaan), dan kemudian terus mengambil acara seterusnya (objek permintaan) jika tiada fungsi panggil balik panggilan balik, laksanakan fungsi panggil balik. Gambar ini menyembunyikan platform yang berkaitan Butiran keserasian, seperti menggunakan

dalam IOCP di bawah Windows untuk menyerahkan status pelaksanaan, mendapatkan permintaan selesai pelaksanaan melalui

dan IOCP secara dalaman melaksanakan butiran kumpulan benang, manakala platform seperti Linux melaksanakan proses ini melalui dan Kumpulan benang

dan

PostQueuedCompletionStatus()GetQueuedCompletionStatus dilaksanakan sendiri di bawah eopll. Selain IO dan sumber komputer lain yang memerlukan panggilan tak segerak, libuvTerdapat juga beberapa

API tak segerak lain
yang tiada kaitan dengan IO tak segerak:

setTimtoutsetInterval

node

  • setTimeout
  • setIntervalBahagian ini terlebih dahulu menerangkan dua API pertama
  • setImmediatePrinsip pelaksanaannya adalah serupa dengan IO tak segerak
  • Ia hanya tidak memerlukan penyertaan kumpulan benang IO
  • : process.nextTick
dan Pemasa yang dibuat akan dimasukkan ke dalam pokok merah-hitam di dalam pemerhati pemasa

Setiap kali
dilaksanakan, objek pemasa akan diambil secara berulang daripada pokok merah-hitam dan menyemak sama ada pemasa melebihi

Jika melebihi, acara (objek permintaan) Tolak ke dalam baris gilir acara dan laksanakan fungsi panggil balik dalam gelung acara

  • Pokok merah-hitam: Biar saya sebutkan secara ringkas di sini bahawa ia adalah pokok binari seimbang khusus yang boleh mengimbangi diri Kecekapan carian pada dasarnya adalah kedalaman pokok binari setTimtoutsetInterval
  • tick
  • O
(

log2n)O(log_2n) O (lo

node ialah cara untuk memanggil IO dan menunggu data dikembalikan (lihat pelaksanaan khusus Ia membenarkan satu utas dalam JavaScript memanggil IO secara tak segerak tanpa menunggu IO). . Pelaksanaan selesai (kerana kumpulan benang IO melakukannya), dan data akhir boleh diperolehi (melalui mod pemerhati: pemerhati IO memperoleh acara penyiapan pelaksanaan daripada kumpulan benang, dan mekanisme gelung peristiwa melaksanakan panggilan balik berikutnya. function)

Perenggan di atas mungkin agak ringkas Kalau masih tak faham, boleh tengok gambar-gambar sebelum ni~

process.nextTick dan <.>setImmediate

Kedua-dua fungsi ini mewakili pelaksanaan tak segerak bagi sesuatu fungsi, jadi mengapa tidak menggunakan

untuk melengkapkannya? setTimeout(() => { ... }, 0)

    Pemasa tidak cukup tepat
  • Pemasa menggunakan pokok merah-hitam untuk mencipta objek pemasa dan operasi berulang, yang membazirkan prestasi
  • Iaitu,
  • lebih ringanprocess.nextTick
Ringan secara khusus: setiap kali kami memanggil

, kami hanya akan meletakkan fungsi panggil balik ke dalam baris gilir dan mengeluarkannya untuk pelaksanaan dalam pusingan seterusnya process.nextTick . Apabila menggunakan kaedah pokok merah-hitam dalam pemasaTickO(l og2n)O(log_2n ) , ialah nextTickO(1 )O(1)

Bagaimana pula dengan

dan process.nextTick Apa perbezaannya? Lagipun, kesemuanya menyimpan fungsi panggil balik yang segera melaksanakan setImmediate

  • dengan keutamaan pelaksanaan yang lebih tinggi daripada fungsi panggil balik process.nextTicksetImmediate
  • dalam tatasusunan . Semua dilaksanakan dalam setiap pusingan gelung acara, dan hasil process.nextTick disimpan dalam senarai terpaut setiap pusingan gelung melaksanakan panggilan balik pertama mengikut urutan setImmediate
Nota: Sebab mengapa. panggil balik

dilaksanakan dahulu Tahap lebih tinggi daripada process.nextTick, kerana gelung peristiwa menyemak pemerhati mengikut tertib, setImmediate milik process.nextTick pemerhati dan idle milik setImmediate pemerhati. checkiedl观察者 > IO 观察者 > check观察者

Pelayan berprestasi tinggi

Untuk pemprosesan soket rangkaian,

juga digunakan pada IO tak segerak dan pengesanan soket rangkaian Permintaan didengar akan membentuk peristiwa dan diserahkan kepada pemerhati IO Gelung peristiwa akan terus memproses peristiwa IO rangkaian ini Jika kita lulus dalam fungsi panggil balik yang sepadan pada tahap node, fungsi panggil balik ini akan berada dalam gelung peristiwa (mengendalikan permintaan rangkaian ini) JavaScrpt

Model pelayan biasa:

    Segerak
  • Setiap proses --> Setiap permintaan
  • Per utas-->Setiap permintaan
Dan

menggunakan pendekatan terdorong peristiwa untuk mengendalikan permintaan ini. Anda tidak perlu membuat urutan tambahan yang sepadan untuk setiap permintaan dan anda boleh meninggalkan penciptaan benang dan overhed untuk memusnahkan benang Pada masa yang sama, kos penukaran konteks adalah sangat rendah kerana terdapat lebih sedikit benang (hanya beberapa utas dilaksanakan secara dalaman) oleh sistem pengendalian. node

Masalah klasik--Masalah longsorPenyelesaian:

Perihalan masalah: Apabila pelayan mula-mula dimulakan, tiada data dalam cache Jika bilangan lawatan adalah besar SQL yang sama akan dihantar Pertanyaan berulang ke pangkalan data menjejaskan prestasi.

Penyelesaian:

const proxy = new events.EventEmitter();
let status = "ready"; // 状态锁,避免反复查询

const select = function(callback) {
    proxy.once("selected", callback);  // 绑定一个只执行一次名为selected的事件
    if(status === "ready") {
        status = "pending";
        // sql
        db.select("SQL", (res) => {
            proxy.emit("selected", res); // 触发事件,返回查询数据
            status = "ready";
        })
    }
}
Salin selepas log masuk

Gunakan once untuk menolak semua panggilan balik permintaan ke dalam baris gilir acara dan manfaatkan cirinya bahawa monitor akan dialih keluar selepas melaksanakannya sekali sahaja bahawa setiap fungsi panggil balik hanya akan dilaksanakan sekali. Untuk pernyataan SQL yang sama, ia dijamin akan dilaksanakan sekali sahaja dari awal hingga akhir pertanyaan yang sama. Ketibaan baharu panggilan yang sama hanya perlu menunggu dalam baris gilir untuk data siap Setelah keputusan ditanya, keputusan boleh digunakan oleh panggilan ini bersama-sama.

Untuk lebih banyak pengetahuan berkaitan pengaturcaraan, sila lawati: Pengajaran Pengaturcaraan! !

Atas ialah kandungan terperinci Mari kita bincangkan tentang pelaksanaan tak segerak dan pemanduan acara dalam Node. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!