Mana yang lebih baik untuk tugas bersamaan di node.js? Serat? Pekerja web? atau Threads?

111

Saya tersandung node.js beberapa waktu lalu dan sangat menyukainya. Tetapi segera saya menemukan bahwa ia kurang memiliki kemampuan untuk melakukan tugas-tugas intensif CPU. Jadi, saya mulai googling dan mendapatkan jawaban ini untuk menyelesaikan masalah: Fiber, Webworkers, dan Threads (thread-a-gogo). Sekarang yang mana yang akan digunakan adalah kebingungan dan salah satunya pasti perlu digunakan - lagipula apa tujuan memiliki server yang hanya bagus di IO dan tidak ada yang lain? Saran dibutuhkan!

MEMPERBARUI:

Saya sedang memikirkan jalan keluar-larut; hanya membutuhkan saran untuk itu. Sekarang, yang saya pikirkan adalah ini: Mari kita memiliki beberapa utas (menggunakan thread_a_gogo atau mungkin pekerja web). Sekarang, ketika kita membutuhkan lebih banyak dari mereka, kita dapat menciptakan lebih banyak. Tetapi akan ada batasan dalam proses pembuatan. (tidak tersirat oleh sistem tetapi mungkin karena overhead). Sekarang, ketika kita melebihi batas, kita bisa membuat simpul baru, dan mulai membuat utas di atasnya. Dengan cara ini, ini dapat terus berjalan hingga kita mencapai batas tertentu (bagaimanapun juga, proses juga memiliki overhead yang besar). Ketika batas ini tercapai, kami mulai mengantri tugas. Setiap kali utas menjadi gratis, itu akan diberi tugas baru. Dengan cara ini, ini bisa berjalan lancar.

Jadi, itulah yang saya pikirkan. Apakah ide ini bagus? Saya agak baru untuk semua proses ini dan hal-hal utas, jadi tidak memiliki keahlian apa pun di dalamnya. Silakan bagikan pendapat Anda.

Terima kasih. :)

Parth Thakkar
sumber
Harap diperhatikan: Pekerja adalah spesifikasi browser- bukan fitur Javascript.
FredTheWebGuy
Nah, saya melihat itu. Pertanyaan saya adalah tentang node.js - kode server dan bukan tentang sisi klien!
Parth Thakkar
Hanya klarifikasi- Saya melihat bahwa pertanyaan asli adalah tentang Webworkers di NodeJs, yang tidak mungkin- NodeJ menggunakan "Threads". Namun, ada modul NodeJS yang beredar yang memungkinkan sintaks WebWorker di dalam runtime NodeJs.
FredTheWebGuy

Jawaban:

331

Node memiliki paradigma yang sama sekali berbeda dan setelah ditangkap dengan benar, akan lebih mudah untuk melihat cara berbeda dalam memecahkan masalah. Anda tidak perlu banyak utas dalam aplikasi Node (1) karena Anda memiliki cara berbeda untuk melakukan hal yang sama. Anda membuat banyak proses; tetapi sangat sangat berbeda dari, misalnya bagaimana mpm Prefork Server Web Apache lakukan.

Untuk saat ini, anggap saja kita hanya memiliki satu inti CPU dan kita akan mengembangkan aplikasi (dengan cara Node) untuk melakukan beberapa pekerjaan. Tugas kita adalah memproses file besar yang menjalankan isinya byte-by-byte. Cara terbaik untuk perangkat lunak kami adalah memulai pekerjaan dari awal file, ikuti byte-by-byte sampai akhir.

- Hei, Hasan, saya kira Anda adalah seorang pemula atau sekolah yang sangat tua dari zaman Kakek saya !!! Mengapa Anda tidak membuat beberapa utas dan membuatnya lebih cepat?

- Oh, kami hanya memiliki satu inti CPU.

-- Terus? Buat beberapa utas, lebih cepat!

- Ini tidak bekerja seperti itu. Jika saya membuat utas, saya akan membuatnya lebih lambat. Karena saya akan menambahkan banyak overhead ke sistem untuk beralih antar utas, mencoba memberi mereka waktu yang cukup, dan di dalam proses saya, mencoba berkomunikasi di antara utas ini. Selain semua fakta ini, saya juga harus memikirkan tentang bagaimana saya akan membagi satu pekerjaan menjadi beberapa bagian yang dapat dilakukan secara paralel.

- Oke oke, saya melihat Anda miskin. Ayo gunakan komputer saya, ini memiliki 32 inti!

- Wow, kamu luar biasa temanku, terima kasih banyak. Saya menghargainya!

Lalu kami kembali bekerja. Sekarang kami memiliki 32 inti cpu berkat teman kaya kami. Aturan yang harus kita patuhi baru saja berubah. Sekarang kami ingin memanfaatkan semua kekayaan yang kami berikan ini.

Untuk menggunakan banyak inti, kita perlu menemukan cara untuk membagi pekerjaan kita menjadi beberapa bagian yang dapat kita tangani secara paralel. Jika bukan Node, kami akan menggunakan utas untuk ini; 32 utas, satu untuk setiap inti cpu. Namun, karena kami memiliki Node, kami akan membuat 32 proses Node.

Thread dapat menjadi alternatif yang baik untuk proses Node, bahkan mungkin cara yang lebih baik; tetapi hanya dalam jenis pekerjaan tertentu yang pekerjaannya sudah ditentukan dan kami memiliki kendali penuh atas cara menanganinya. Selain ini, untuk setiap jenis masalah lain di mana pekerjaan berasal dari luar dengan cara yang tidak dapat kami kendalikan dan kami ingin menjawab secepat mungkin, cara Node sangat unggul.

- Hei, Hasan, apakah kamu masih bekerja single-threaded? Ada apa denganmu, bung? Saya baru saja memberikan apa yang Anda inginkan. Anda tidak punya alasan lagi. Buat utas, buat itu berjalan lebih cepat.

- Saya telah membagi pekerjaan menjadi beberapa bagian dan setiap proses akan mengerjakan salah satu bagian ini secara paralel.

- Mengapa Anda tidak membuat utas?

- Maaf, menurutku itu tidak bisa digunakan. Anda dapat mengambil komputer Anda jika Anda mau?

- Tidak oke, saya keren, saya hanya tidak mengerti mengapa Anda tidak menggunakan utas?

- Terima kasih untuk komputernya. :) Saya sudah membagi pekerjaan menjadi beberapa bagian dan saya membuat proses untuk mengerjakan bagian-bagian ini secara paralel. Semua inti CPU akan digunakan sepenuhnya. Saya bisa melakukan ini dengan utas alih-alih proses; tetapi Node memiliki cara ini dan bos saya Parth Thakkar ingin saya menggunakan Node.

- Oke, beri tahu saya jika Anda membutuhkan komputer lain. : hal

Jika saya membuat 33 proses, alih-alih 32, penjadwal sistem operasi akan menjeda utas, memulai yang lain, menjeda setelah beberapa siklus, memulai yang lain lagi ... Ini adalah pengeluaran tambahan yang tidak perlu. Saya tidak mau itu. Faktanya, pada sistem dengan 32 core, saya bahkan tidak ingin membuat persis 32 proses, 31 bisa lebih bagus . Karena bukan hanya aplikasi saya yang akan bekerja pada sistem ini. Meninggalkan sedikit ruang untuk hal-hal lain bisa menjadi baik, terutama jika kita memiliki 32 kamar.

Saya yakin kita berada di halaman yang sama sekarang tentang penggunaan prosesor sepenuhnya untuk tugas-tugas intensif CPU .

- Hmm, Hasan, saya minta maaf karena telah sedikit mengejek Anda. Saya yakin saya memahami Anda lebih baik sekarang. Tapi masih ada sesuatu yang saya perlu penjelasannya: Apa yang paling menarik tentang menjalankan ratusan utas? Saya membaca di mana-mana bahwa utas jauh lebih cepat dibuat dan bodoh daripada proses bercabang? Anda membagi proses alih-alih utas dan Anda pikir itu adalah yang tertinggi yang akan Anda dapatkan dengan Node. Lalu apakah Node tidak sesuai untuk jenis pekerjaan ini?

- Jangan khawatir, aku juga keren. Semua orang mengatakan hal-hal ini jadi saya pikir saya sudah terbiasa mendengarnya.

- Jadi? Node tidak bagus untuk ini?

- Node sangat bagus untuk ini meskipun utas juga bisa bagus. Adapun overhead pembuatan thread / proses; pada hal-hal yang sering Anda ulangi, setiap milidetik penting. Namun, saya hanya membuat 32 proses dan itu akan memakan sedikit waktu. Itu hanya akan terjadi sekali. Tidak akan ada bedanya.

- Kapan saya ingin membuat ribuan utas?

- Anda tidak pernah ingin membuat ribuan utas. Namun, pada sistem yang melakukan pekerjaan yang datang dari luar, seperti server web yang memproses permintaan HTTP; jika Anda menggunakan utas untuk setiap permintaan, Anda akan membuat banyak utas, banyak di antaranya.

- Node berbeda sih? Baik?

-- Ya persis. Di sinilah Node benar-benar bersinar. Seperti utas jauh lebih ringan daripada proses, panggilan fungsi jauh lebih ringan daripada utas. Node memanggil fungsi, alih-alih membuat utas. Dalam contoh server web, setiap permintaan masuk menyebabkan panggilan fungsi.

-- Hmm menarik; tetapi Anda hanya dapat menjalankan satu fungsi pada saat yang sama jika Anda tidak menggunakan banyak utas. Bagaimana ini bisa bekerja ketika banyak permintaan tiba di server web pada saat yang bersamaan?

- Anda benar sekali tentang cara menjalankan fungsi, satu per satu, tidak pernah dua fungsi secara paralel. Maksud saya dalam satu proses, hanya satu cakupan kode yang berjalan pada satu waktu. OS Scheduler tidak datang dan menjeda fungsi ini dan beralih ke fungsi lain, kecuali jika menjeda proses untuk memberikan waktu ke proses lain, bukan utas lain dalam proses kami. (2)

- Lalu bagaimana sebuah proses menangani 2 permintaan sekaligus?

- Sebuah proses dapat menangani puluhan ribu permintaan dalam satu waktu selama sistem kami memiliki cukup sumber daya (RAM, Jaringan, dll.). Bagaimana fungsi-fungsi itu berjalan adalah PERBEDAAN KUNCI.

- Hmm, haruskah aku bersemangat sekarang?

- Mungkin :) Node menjalankan loop melalui antrian. Dalam antrian ini adalah pekerjaan kita, yaitu panggilan yang kita mulai untuk memproses permintaan yang masuk. Poin terpenting di sini adalah cara kami mendesain fungsi untuk dijalankan. Alih-alih mulai memproses permintaan dan membuat pemanggil menunggu hingga kami menyelesaikan pekerjaan, kami dengan cepat mengakhiri fungsi kami setelah melakukan sejumlah pekerjaan yang dapat diterima. Ketika kita sampai pada titik di mana kita perlu menunggu komponen lain untuk melakukan beberapa pekerjaan dan mengembalikan nilai kepada kita, alih-alih menunggu itu, kita cukup menyelesaikan fungsi kita dengan menambahkan sisa pekerjaan ke antrian.

- Kedengarannya terlalu rumit?

- Tidak, tidak, saya mungkin terdengar rumit; tetapi sistemnya sendiri sangat sederhana dan sangat masuk akal.

Sekarang saya ingin berhenti mengutip dialog antara kedua pengembang ini dan menyelesaikan jawaban saya setelah contoh singkat terakhir tentang cara kerja fungsi ini.

Dengan cara ini, kami melakukan apa yang biasanya dilakukan OS Scheduler. Kami menghentikan pekerjaan kami di beberapa titik dan membiarkan panggilan fungsi lain (seperti utas lain dalam lingkungan multi-utas) berjalan sampai kami mendapatkan giliran kami lagi. Ini jauh lebih baik daripada menyerahkan pekerjaan ke OS Scheduler yang mencoba memberikan waktu yang tepat untuk setiap utas pada sistem. Kami tahu apa yang kami lakukan jauh lebih baik daripada OS Scheduler dan kami diharapkan berhenti ketika kami harus berhenti.

Di bawah ini adalah contoh sederhana di mana kami membuka file dan membacanya untuk melakukan beberapa pekerjaan pada data.

Cara Sinkron:

Open File
Repeat This:    
    Read Some
    Do the work

Cara Asynchronous:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

Seperti yang Anda lihat, fungsi kami meminta sistem untuk membuka file dan tidak menunggu untuk dibuka. Itu selesai sendiri dengan memberikan langkah selanjutnya setelah file siap. Ketika kita kembali, Node menjalankan pemanggilan fungsi lain pada antrian. Setelah menjalankan semua fungsi, event loop berpindah ke giliran berikutnya ...

Singkatnya, Node memiliki paradigma yang sama sekali berbeda dari pengembangan multi-threaded; tetapi ini tidak berarti bahwa ia kekurangan banyak hal. Untuk pekerjaan sinkron (di mana kita dapat memutuskan urutan dan cara pemrosesan), ini berfungsi serta paralelisme multi-utas. Untuk pekerjaan yang datang dari luar seperti permintaan ke server, itu lebih baik.


(1) Kecuali Anda sedang membangun perpustakaan dalam bahasa lain seperti C / C ++ dalam hal ini Anda masih tidak membuat utas untuk membagi pekerjaan. Untuk jenis pekerjaan ini Anda memiliki dua utas, salah satunya akan melanjutkan komunikasi dengan Node sementara yang lain melakukan pekerjaan sebenarnya.

(2) Faktanya, setiap proses Node memiliki banyak utas karena alasan yang sama yang saya sebutkan di catatan kaki pertama. Namun ini tidak seperti 1000 utas melakukan pekerjaan serupa. Utas tambahan tersebut adalah untuk hal-hal seperti menerima peristiwa IO dan menangani pengiriman pesan antar-proses.

UPDATE (Sebagai balasan untuk pertanyaan bagus di komentar)

@Mark, terima kasih atas kritik yang membangun. Dalam paradigma Node, Anda tidak boleh memiliki fungsi yang membutuhkan waktu terlalu lama untuk diproses kecuali semua panggilan lain dalam antrean dirancang untuk dijalankan satu demi satu. Dalam kasus tugas yang mahal secara komputasi, jika kita melihat gambar secara lengkap, kita melihat bahwa ini bukan pertanyaan "Haruskah kita menggunakan utas atau proses?" tetapi pertanyaan tentang "Bagaimana kami dapat membagi tugas ini dengan cara yang seimbang menjadi beberapa sub-tugas yang dapat kami jalankan secara paralel menggunakan beberapa inti CPU pada sistem?" Katakanlah kita akan memproses 400 file video pada sistem dengan 8 core. Jika kita ingin memproses satu file dalam satu waktu, maka kita memerlukan sistem yang akan memproses bagian yang berbeda dari file yang sama dalam hal ini, mungkin sistem proses tunggal multi-threaded akan lebih mudah dibangun dan bahkan lebih efisien. Kita masih bisa menggunakan Node untuk ini dengan menjalankan banyak proses dan meneruskan pesan di antara mereka ketika berbagi status / komunikasi diperlukan. Seperti yang saya katakan sebelumnya, pendekatan multi-proses dengan Node adalahserta pendekatan multi-utas dalam tugas semacam ini; tapi tidak lebih dari itu. Sekali lagi, seperti yang saya katakan sebelumnya, situasi Node bersinar adalah ketika kita memiliki tugas-tugas ini yang datang sebagai input ke sistem dari berbagai sumber karena menyimpan banyak koneksi secara bersamaan jauh lebih ringan di Node dibandingkan dengan thread-per-connection atau process-per-connection. sistem.

Adapun setTimeout(...,0)panggilan; kadang-kadang memberikan jeda selama tugas yang memakan waktu untuk memungkinkan panggilan dalam antrian memiliki bagian pemrosesan mereka dapat diperlukan. Membagi tugas dengan cara yang berbeda dapat menyelamatkan Anda dari ini; tetapi tetap saja, ini sebenarnya bukan peretasan, ini hanyalah cara kerja antrean acara. Selain itu, menggunakan process.nextTickuntuk tujuan ini jauh lebih baik karena saat Anda menggunakan setTimeout, penghitungan dan pemeriksaan waktu yang telah berlalu akan diperlukan, sementara process.nextTickyang sebenarnya kami inginkan adalah: "Hai tugas, kembali ke akhir antrean, Anda telah menggunakan bagian Anda! "

hasanyasin
sumber
9
Luar biasa! Luar biasa! Saya menyukai cara Anda menjawab pertanyaan ini! :)
Parth Thakkar
48
Tentu :) Saya benar-benar tidak percaya ada orang yang sangat jahat di luar sana yang memilih artikel jawaban ini! Penanya menyebutnya "Luar Biasa!" dan seorang penulis buku menawarkan saya menulis di situs webnya setelah melihat ini; tetapi beberapa orang jenius di luar sana menolaknya. Mengapa Anda tidak membagikan kualitas intelektual Anda yang cemerlang dan mengomentarinya alih-alih memberikan suara negatif yang kejam dan diam-diam, ya? Mengapa sesuatu yang baik sangat mengganggu Anda? Mengapa Anda ingin mencegah sesuatu yang bermanfaat untuk menjangkau orang lain yang benar-benar dapat memperoleh manfaat darinya?
hasanyasin
9
Ini bukanlah jawaban yang sepenuhnya adil. Bagaimana dengan tugas yang mahal secara komputasi, di mana kita tidak dapat "mengakhiri dengan cepat" pemanggilan fungsi kita? Saya percaya beberapa orang menggunakan beberapa setTimeout(...,0)peretasan untuk ini, tetapi menggunakan utas terpisah dalam skenario ini pasti akan lebih baik?
mpen
3
@hasanyasin Ini adalah penjelasan terbaik tentang node yang saya temukan sejauh ini! :)
Venemo
7
@Mark Secara umum, jika secara komputasi mahal, ada opsi / modul untuk pekerja tapak / proses ... Secara umum untuk jenis hal ini, saya menggunakan Antrian Pesan, dan memiliki proses pekerja yang menangani tugas di waktu dari antrian, dan kerjakan tugas itu. Ini juga memungkinkan penskalaan ke beberapa server. Sejalan dengan itu, Substack memiliki banyak modul yang diarahkan pada penyediaan dan penskalaan yang dapat Anda lihat.
Tracker1
34

(Pembaruan 2016: Pekerja web akan masuk ke io.js - garpu Node.js Node.js v7 - lihat di bawah.)

(Pembaruan 2017: Pekerja web tidak masuk ke Node.js v7 atau v8 - lihat di bawah.)

(Update 2018: pekerja Web yang akan menjadi Node.js Node v10.5.0 - lihat di bawah ini.)

Beberapa klarifikasi

Setelah membaca jawaban di atas, saya ingin menunjukkan bahwa tidak ada pekerja web yang bertentangan dengan filosofi JavaScript secara umum dan Node pada khususnya terkait konkurensi. (Jika ada, itu tidak akan dibahas oleh WHATWG, apalagi diterapkan di browser).

Anda dapat menganggap pekerja web sebagai layanan mikro ringan yang diakses secara asinkron. Tidak ada negara bagian yang dibagikan. Tidak ada masalah penguncian. Tidak ada pemblokiran. Tidak perlu sinkronisasi. Sama seperti ketika Anda menggunakan layanan RESTful dari program Node Anda, Anda tidak perlu khawatir bahwa program tersebut sekarang "multithread" karena layanan RESTful tidak berada di thread yang sama dengan loop peristiwa Anda sendiri. Ini hanya layanan terpisah yang Anda akses secara asinkron dan itulah yang penting.

Hal yang sama berlaku untuk pekerja web. Ini hanya API untuk berkomunikasi dengan kode yang berjalan dalam konteks yang benar-benar terpisah dan apakah itu di utas yang berbeda, proses yang berbeda, cgroup yang berbeda, zona, wadah atau mesin yang berbeda sama sekali tidak relevan, karena API yang sangat asinkron, non-pemblokiran, dengan semua data yang diteruskan oleh nilai.

Faktanya, pekerja web secara konseptual sangat cocok untuk Node yang - karena banyak orang tidak menyadarinya - secara kebetulan menggunakan utas cukup banyak, dan pada kenyataannya "semuanya berjalan secara paralel kecuali kode Anda" - lihat:

Tetapi pekerja web bahkan tidak perlu diimplementasikan menggunakan utas. Anda dapat menggunakan proses, utas hijau, atau bahkan layanan RESTful di cloud - selama API pekerja web digunakan. Seluruh keindahan pesan yang melewati API dengan semantik panggilan menurut nilai adalah bahwa implementasi yang mendasarinya tidak terlalu relevan, karena detail model konkurensi tidak akan terungkap.

Perulangan peristiwa utas tunggal sangat cocok untuk operasi terikat I / O. Itu tidak bekerja dengan baik untuk operasi yang terikat dengan CPU, terutama yang berjalan lama. Untuk itu kita perlu menelurkan lebih banyak proses atau menggunakan utas. Mengelola proses anak dan komunikasi antar proses dengan cara portabel bisa jadi sangat sulit dan sering dianggap berlebihan untuk tugas-tugas sederhana, sementara menggunakan utas berarti menangani masalah kunci dan sinkronisasi yang sangat sulit dilakukan dengan benar.

Apa yang sering direkomendasikan adalah membagi operasi yang terikat dengan CPU yang sudah berjalan lama menjadi tugas-tugas yang lebih kecil (seperti contoh di bagian "Jawaban asli" dari jawaban saya untuk Mempercepat setInterval ) tetapi tidak selalu praktis dan tidak menggunakan lebih banyak dari satu inti CPU.

Saya menulisnya untuk mengklarifikasi komentar yang pada dasarnya mengatakan bahwa pekerja web dibuat untuk browser, bukan server (lupa bahwa hal itu dapat dikatakan tentang hampir semua hal di JavaScript).

Modul node

Ada beberapa modul yang seharusnya menambahkan Pekerja Web ke Node:

Saya belum pernah menggunakan satu pun dari mereka tetapi saya memiliki dua pengamatan singkat yang mungkin relevan: per Maret 2015, node-webworker terakhir diperbarui 4 tahun yang lalu dan node-webworker-threads terakhir diperbarui sebulan yang lalu. Saya juga melihat dalam contoh penggunaan node-webworker-threads bahwa Anda dapat menggunakan fungsi alih-alih nama file sebagai argumen untuk konstruktor Pekerja yang tampaknya dapat menyebabkan masalah halus jika diimplementasikan menggunakan utas yang berbagi memori (kecuali fungsi digunakan hanya untuk metode .toString () dan jika tidak dikompilasi dalam lingkungan yang berbeda, dalam hal ini mungkin baik-baik saja - saya harus melihat lebih dalam, hanya berbagi pengamatan saya di sini).

Jika ada proyek relevan lainnya yang mengimplementasikan API pekerja web di Node, silakan tinggalkan komentar.

Perbarui 1

Aku tidak tahu itu namun pada saat penulisan tetapi kebetulan satu hari sebelum saya menulis jawaban ini Web Workers ditambahkan ke io.js .

( io.js adalah cabang dari Node.js - lihat: Mengapa io.js memutuskan untuk bercabang Node.js , wawancara InfoWorld dengan Mikeal Rogers, untuk info lebih lanjut.)

Tidak hanya membuktikan bahwa tidak ada sesuatu pun di web worker yang bertentangan dengan filosofi JavaScript secara umum dan Node pada khususnya terkait konkurensi, tetapi juga dapat mengakibatkan pekerja web menjadi warga negara kelas satu dalam JavaScript sisi server seperti io. js (dan mungkin Node.js di masa mendatang) seperti yang sudah ada di JavaScript sisi klien di semua browser modern .

Perbarui 2

Dalam Pembaruan 1 dan tweet saya, saya merujuk ke permintaan tarik io.js # 1159 yang sekarang dialihkan ke Node PR # 1159 yang ditutup pada 8 Juli dan diganti dengan Node PR # 2133 - yang masih terbuka. Ada beberapa diskusi yang terjadi di bawah permintaan tarik tersebut yang mungkin memberikan beberapa info terkini tentang status pekerja Web di io.js / Node.js.

Perbarui 3

Info terbaru - terima kasih kepada NiCk Newman untuk mempostingnya di komentar: Ada pekerja: implementasi awal yang dilakukan oleh Petka Antonov mulai 6 Sep 2015 yang dapat diunduh dan dicoba di pohon ini . Lihat komentar NiCk Newman untuk detailnya.

Perbarui 4

Per Mei 2016 , komentar terakhir pada PR # 2133 - pekerja yang masih terbuka : implementasi awal berusia 3 bulan. Pada tanggal 30 Mei Matheus Moreira meminta saya untuk memposting pembaruan untuk jawaban ini di komentar di bawah dan dia menanyakan status saat ini dari fitur ini di komentar PR.

Jawaban pertama dalam diskusi PR skeptis tetapi kemudian Ben Noordhuis menulis bahwa " Menggabungkan ini dalam satu bentuk atau lainnya ada di daftar rencana saya untuk v7".

Semua komentar lain sepertinya mendukung itu dan pada Juli 2016 tampaknya Web Workers harus tersedia di versi Node berikutnya , versi 7.0 yang direncanakan akan dirilis pada Oktober 2016 (tidak harus dalam bentuk PR yang sama persis).

Terima kasih kepada Matheus Moreira karena telah menunjukkannya di komentar dan menghidupkan kembali diskusi di GitHub.

Perbarui 5

Mulai Juli 2016, ada beberapa modul di npm yang tidak tersedia sebelumnya - untuk daftar lengkap modul yang relevan, telusuri npm untuk pekerja, pekerja web, dll. Jika ada sesuatu yang berhasil atau tidak berhasil untuk Anda, silakan kirim komentar.

Perbarui 6

Pada Januari 2017 , tidak mungkin pekerja web akan digabung ke Node.js.

Permintaan tarik pekerja # 2133 : implementasi awal oleh Petka Antonov mulai 8 Juli 2015 akhirnya ditutup oleh Ben Noordhuis pada tanggal 11 Desember 2016 yang berkomentar bahwa "dukungan multi-threading menambahkan terlalu banyak mode kegagalan baru untuk keuntungan yang tidak cukup" dan "kami juga dapat melakukannya dengan menggunakan cara yang lebih tradisional seperti memori bersama dan serialisasi yang lebih efisien. "

Untuk informasi lebih lanjut lihat komentar ke PR 2133 di GitHub.

Terima kasih sekali lagi kepada Matheus Moreira karena telah menunjukkannya di komentar.

Perbarui 6

Dengan senang hati saya umumkan bahwa beberapa hari yang lalu, pada bulan Juni 2018 pekerja web muncul di Node v10.5.0 sebagai fitur eksperimental yang diaktifkan dengan --experimental-workerbendera.

Untuk info lebih lanjut, lihat:

🎉🎉🎉 Akhirnya! Saya dapat membuat pembaruan ke-7 untuk jawaban Stack Overflow saya yang berusia 3 tahun di mana saya berpendapat bahwa threading a la web worker tidak bertentangan dengan filosofi Node, hanya saja kali ini mengatakan bahwa kami akhirnya mendapatkannya! 😜👍

rsp
sumber
1
@NiCNew Terima kasih. Saya melihat bahwa permintaan penarikan asli di io.js ditutup sekarang dan diganti dengan yang lain - dengan beberapa diskusi di sana di komentar permintaan tarik di GitHub, mungkin Anda akan dapat menemukan beberapa info di sana. Lihat: Perbarui 2 di jawaban saya.
rsp
1
Ya, sepertinya mereka baru saja memperbaiki masalah libuv terakhir. Saya bertanya-tanya kapan saya bisa mendapatkan modul ini. Tidak sabar! Terima kasih telah memberi kami informasi terbaru ~ Edit: Baru saja diinisialisasi: github.com/petkaantonov/io.js/commit/… Ini dia, dia datang!
NiCk Newman
1
Ya, ini siaran langsung. (Belum diimplementasikan secara resmi) tetapi Anda dapat mendownload sumbernya di sini: github.com/petkaantonov/io.js/tree/… dan kompilasi jika Anda ingin mengujinya! Saya melakukannya sekarang ~
NiCk Newman
1
@NiCkNewman Terima kasih atas info baru - Saya menambahkannya ke jawabannya.
rsp
1
Bisakah Anda memberi tahu kami tentang status workersimplementasi Node.js ? Komentar terakhir di PR # 2133 berasal dari Februari; para pengembang tampaknya mengalami masalah dan tidak ada komentar yang menunjukkan bahwa masalah telah diselesaikan.
Matheus Moreira
8

Saya berasal dari pemikiran lama di mana kami menggunakan multi-threading untuk membuat perangkat lunak dengan cepat. Selama 3 tahun terakhir saya telah menggunakan Node.js dan merupakan pendukung besar itu. Seperti yang dijelaskan hasanyasin secara detail bagaimana node bekerja dan konsep fungsi asyncrous. Tapi izinkan saya menambahkan beberapa hal di sini.

Kembali ke masa lalu dengan inti tunggal dan kecepatan jam yang lebih rendah, kami mencoba berbagai cara untuk membuat perangkat lunak bekerja cepat dan paralel. di hari-hari DOS kami menggunakan untuk menjalankan satu program dalam satu waktu. Kemudian di windows kami mulai menjalankan beberapa aplikasi (proses) secara bersamaan. Konsep seperti preemptive dan non-preemptive (atau kooperatif) di mana diuji. kita tahu sekarang bahwa preemptive adalah jawaban untuk tugas multi-pemrosesan yang lebih baik pada komputer inti tunggal. Seiring datangnya konsep proses / tugas dan pengalihan konteks. Dari konsep utas untuk lebih mengurangi beban alih konteks proses. Benang yang diciptakan sebagai alternatif ringan untuk menghasilkan proses baru.

Jadi suka atau tidak sinyal utas atau tidak multi-core atau single core proses Anda akan didahului dan waktu diiris oleh OS.

Nodejs adalah proses tunggal dan menyediakan mekanisme asinkron. Di sini, pekerjaan dikirim ke OS yang berada di bawah untuk melakukan tugas sementara kita menunggu dalam loop acara untuk menyelesaikan tugas. Setelah kami mendapatkan sinyal hijau dari OS, kami melakukan apa pun yang perlu kami lakukan. Sekarang dengan cara ini multi-tasking kooperatif / non-preemptive, jadi kita tidak boleh memblokir loop acara untuk jangka waktu yang sangat lama jika tidak kita akan menurunkan aplikasi kita dengan sangat cepat.
Jadi, jika ada tugas yang bersifat memblokir atau sangat memakan waktu, kami harus mencabangnya ke dunia preemptive OS dan utas. ada contoh bagus tentang ini di dokumentasi libuv . Juga jika Anda membaca dokumentasi lebih lanjut Anda menemukan bahwa FileI / O ditangani di thread di node.js .

Jadi Pertama-tama, semuanya ada dalam desain perangkat lunak kami. Kedua, Peralihan konteks selalu terjadi apa pun yang mereka katakan. Thread ada dan masih ada karena suatu alasan, alasannya adalah mereka lebih cepat beralih di antara proses tersebut.

Di bawah tenda di node.js semua c ++ dan utasnya. Dan node menyediakan c ++ cara untuk memperluas fungsionalitasnya dan untuk mempercepat lebih lanjut dengan menggunakan utas di mana mereka adalah suatu keharusan yaitu, memblokir tugas-tugas seperti membaca dari sumber yang menulis ke sumber, analisis data besar, dan sebagainya.

Saya tahu jawaban hasanyasin adalah yang diterima tetapi bagi saya utas akan ada tidak peduli apa yang Anda katakan atau bagaimana Anda menyembunyikannya di balik skrip, kedua tidak ada yang hanya memecah barang ke utas hanya untuk kecepatan sebagian besar dilakukan untuk memblokir tugas. Dan utas berada di tulang belakang Node.js jadi sebelum benar-benar bashing multi-threading sudah benar. Juga utas berbeda dari proses dan batasan memiliki proses node per inti tidak benar-benar berlaku untuk jumlah utas, utas seperti sub tugas untuk suatu proses. sebenarnya utas tidak akan muncul di windows task manager atau perintah atas linux. sekali lagi mereka lebih sedikit berbobot daripada memproses

limplash
sumber
Kode asinkron bukanlah inovasi besar (sebenarnya kita sudah memilikinya selama beberapa dekade) dan multithreading bukanlah teknologi usang untuk diganti. Mereka adalah alat yang berbeda dengan pengorbanan yang berbeda, dan bahkan dapat digabungkan dengan cukup baik. Setiap kali Anda menjalankan node-cluster, Anda sebenarnya menjalankan beberapa "utas" (proses dalam kasus ini, tetapi hal yang sama dapat dicapai dengan utas, dan bahkan lebih ringan). Atau ambil Erlang or Go, yang dapat menjalankan ribuan benang hijau ...
Hejazzman
Saya pikir poin utama yang kami lewatkan adalah bahwa proses di bawah OS akan selalu dilakukan dengan cara preemptive untuk memberikan keadilan. Juga dengan multi prosesor Anda dapat memiliki eksekusi kode paralel yang sebenarnya tetapi bahkan kemudian Anda akan memiliki preemption. Pekerjaan asinkron juga dilakukan oleh OS di beberapa untuk suatu proses.
limplash
4

Saya tidak yakin apakah webworker relevan dalam hal ini, mereka adalah teknologi sisi klien (berjalan di browser), sementara node.js berjalan di server. Serat, sejauh yang saya mengerti, juga memblokir, yaitu mereka multitasking sukarela, sehingga Anda dapat menggunakannya, tetapi harus mengelola sakelar konteks sendiri yield. Utas mungkin sebenarnya yang Anda butuhkan, tetapi saya tidak tahu seberapa matang mereka di node.js.

lanzz
sumber
3
hanya untuk info Anda, webworkers telah (sebagian) diadaptasi di node.js. Dan tersedia sebagai node-workerspaket. Lihat ini: github.com/cramforce/node-worker
Parth Thakkar
Senang mengetahui, terima kasih. Dokumen sangat langka, saya tidak tahu apakah ini berjalan di utas terpisah, proses, atau hanya berjalan dalam proses yang sama, dan saya tidak punya waktu untuk menggali kodenya, jadi saya tidak tahu apakah itu akan bekerja untuk kasus Anda.
lanzz
@ParthThakkar: Proyek itu belum tersentuh dalam 3 tahun (2 saat Anda memposting), dan belum berhasil melewati 0,0.1.
mpen
@ Mark: Alasan ketidaktahuan saya adalah karena saya belum menjadi programmer profesional. Heck, saya bahkan belum di universitas. Saya masih SMA, yang terus membaca tentang pemrograman - selain mengelola tugas sekolah. Jadi, tidak mungkin bagi saya untuk memiliki pengetahuan tentang semua masalah seperti itu. Saya baru saja memposting apa yang saya tahu ...
Parth Thakkar
@ Mark: Meskipun Anda senang menunjukkan hal itu tentang sejarah proyek. Hal-hal seperti itu akan diurus dalam tanggapan masa depan saya !! :)
Parth Thakkar
3

worker_threadstelah diterapkan dan dikirim dengan bendera di [email protected]. Ini masih merupakan implementasi awal dan lebih banyak upaya diperlukan untuk membuatnya lebih efisien dalam rilis mendatang. Layak untuk dicoba terbaru node.

motss
sumber
2

Dalam banyak pendapat pengembang Node, salah satu bagian terbaik dari Node sebenarnya adalah sifat single-threaded-nya. Threads memperkenalkan banyak kesulitan dengan resource bersama yang sepenuhnya dihindari oleh Node dengan melakukan apa pun selain IO non-pemblokiran.

Itu tidak berarti bahwa Node terbatas pada satu utas. Hanya saja metode untuk mendapatkan konkurensi berulir berbeda dari yang Anda cari. Cara standar untuk menangani utas adalah dengan cluster modul yang menjadi standar dengan Node itu sendiri. Ini adalah pendekatan yang lebih sederhana untuk utas daripada menanganinya secara manual dalam kode Anda.

Untuk menangani pemrograman asinkron dalam kode Anda (seperti, menghindari piramida callback bersarang), komponen [Future] di pustaka Fibers adalah pilihan yang tepat. Saya juga menyarankan Anda untuk memeriksa Asyncblock yang didasarkan pada Serat. Serat bagus karena memungkinkan Anda menyembunyikan panggilan balik dengan menduplikasi tumpukan dan kemudian melompat di antara tumpukan pada satu utas sesuai kebutuhan. Menghemat kerumitan utas nyata sekaligus memberi Anda manfaat. Kelemahannya adalah bahwa jejak tumpukan bisa menjadi sedikit aneh saat menggunakan Serat, tetapi tidak terlalu buruk.

Jika Anda tidak perlu khawatir tentang hal-hal asinkron dan lebih hanya tertarik untuk melakukan banyak pemrosesan tanpa memblokir, panggilan sederhana ke process.nextTick (callback) sesekali adalah yang Anda butuhkan.

genericdave.dll
sumber
Nah, saran Anda - tentang cluster - adalah apa yang awalnya saya pikirkan. Tetapi masalah dengan itu adalah overhead mereka - instance baru v8 harus dijalankan setiap kali proses baru bercabang (~ 30ms, 10MB). Jadi, Anda tidak dapat membuat banyak dari mereka. Ini diambil langsung dari dokumen node: Node anak ini (tentang child_processes) masih merupakan instance baru dari V8. Asumsikan setidaknya 30ms startup dan memori 10mb untuk setiap Node baru. Artinya, Anda tidak dapat membuat ribuan dari mereka.
Parth Thakkar
1
Inilah ide cluster. Anda menjalankan satu pekerja per inti cpu. Lebih dari itu kemungkinan besar tidak perlu. Bahkan tugas intensif cpu akan berfungsi dengan baik dengan gaya asinkron. Namun, jika Anda benar - benar membutuhkan utas lengkap, Anda mungkin harus mempertimbangkan untuk pindah ke backend server lain sepenuhnya.
genericdave
1

Mungkin beberapa informasi lebih lanjut tentang tugas apa yang Anda lakukan akan membantu. Mengapa Anda perlu (seperti yang Anda sebutkan dalam komentar Anda untuk jawaban genericdave) perlu membuat ribuan dari mereka? Cara yang biasa untuk melakukan hal semacam ini di Node adalah memulai proses pekerja (menggunakan garpu atau metode lain) yang selalu berjalan dan dapat dikomunikasikan menggunakan pesan. Dengan kata lain, jangan memulai pekerja baru setiap kali Anda perlu melakukan tugas apa pun yang sedang Anda lakukan, tetapi cukup kirim pesan ke pekerja yang sudah berjalan dan dapatkan respons setelah selesai. Sejujurnya, saya tidak bisa melihat itu memulai ribuan utas yang sebenarnya juga akan sangat efisien, Anda masih dibatasi oleh CPU Anda.

Sekarang, setelah mengatakan semua itu, saya telah melakukan banyak pekerjaan dengan Hook.io akhir-akhir ini yang tampaknya bekerja sangat baik untuk tugas-tugas pemuatan semacam ini ke proses lain, mungkin itu dapat mencapai apa yang Anda butuhkan.

kbjr.dll
sumber