Bagaimana Cara Node.js Mendapatkan Concurrency? - CRUDPRO

Bagaimana Cara Node.js Mendapatkan Concurrency?

Bagaimana Cara Node.js Mendapatkan Concurrency?

Jika Anda pernah mengunjungi bandara yang lumayan besar, Anda tentu memperhatikan beberapa penerbangan lepas landas atau mendarat pada pukul tertentu dalam sehari.

Saat ini bayangkan bagaimana jadi jika bandara hanya bisa menangani satu penerbangan pada hari tertentu. Perjalanan global akan terhenti.

Bagaimana Cara Node.js Mendapatkan Concurrency?

Menangani beberapa penerbangan sekaligus memungkinkan perjalanan udara. Kemampuan ini dikenal juga sebagai concurrency dan merupakan kunci untuk melakukan lebih banyak pekerjaan dengan waktu dan sumber daya yang terbatas.

Jika Anda menerapkan konsep itu pada pengembangan perangkat lunak, sebuah aplikasi dikatakan bersamaan jika dapat menangani banyak tugas secara bersamaan.

Bagaimana reaksi Anda jika Anda mengunjungi beranda Amazon dan mendapatkan pesan yang mengatakan jika jumlah maksimum pengguna sudah mengakses situs web dan Anda harus menunggu giliran?

Kemungkinan Anda tidak akan pernah mengunjungi website itu lagi dan Amazon akan kehilangan pelanggan potensial.

Sebagai pengembang, saat kami menggunakan platform (seperti server website) untuk menjalankan aplikasi, kami berharap platform itu mendukung sikap bersamaan. Seringkali, model konkurensi platform atau kerangka kerja cukup mudah dimengerti.

Tapi saya telah melihat jika pengembang kerap bingung tentang konkurensi di Node.js. Mereka tahu mengenai Event Loop tapi tidak tahu cara kerjanya yang sebenarnya.

Dalam posting ini, tujuan saya untuk menghapus semua kebingungan tentang konkurensi di Node.js.

Rintangan terbesar untuk Konkurensi

Kenapa sulit untuk mencapai konkurensi?

Apakah ada rintangan mendasar untuk konkurensi dalam sistem perangkat lunak?

Ya

Hambatan utama untuk konkurensi lamban dan memblokir operasi input-output.

Operasi I/O adalah salah satu operasi fundamental dari sistem computer. Tetapi mereka yang paling lamban.

Mengakses RAM ialah dalam urutan nanodetik. Mengakses disk bahkan lebih lambat (dalam urutan milidetik).

Bandwidth share cerita yang sama.

RAM memiliki kecepatan transfer dalam urutan GB/detik sementara disk dan jaringan bisa bervariasi dari MB/dtk hingga GB/dtk.

Meskipun I/O bukan perhitungan yang berat, ini menimbulkan penundaan antara saat permintaan dan saat operasi selesai.

, I/O bukan hanya masalah perangkat lunak. Factor manusia kemungkinan bahkan lebih penting. Penundaan terbesar dalam aplikasi berasal dari menunggu input pengguna (misalkan, click mouse dan penekanan tombol). Penundaan ini lebih besar daripada yang disebabkan oleh akses disk atau latensi jaringan.

Pada akhirnya, lamban dan pemblokiran I/O mendorong Anda ke arah kode sinkron yang tidak bersamaan.

Bagaimana basis mengatasi pemblokiran I/O?

Tidak ada keraguan jika lambat dan pemblokiran I/O ialah rintangan terbesar untuk konkurensi.

Maka bagaimana beberapa platform mengatasi masalah ini?

Silahkan kita lihat beberapa metode populer untuk mengaktifkan konkurensi.

Multi-Threading

Multi-threading ialah pendekatan umum untuk mendukung konkurensi. Ini digunakan oleh bahasa populer seperti Java.

Dalam pemrograman I/O pemblokiran tradisional, pemanggilan fungsi yang membuat permintaan I/O akan memblokir eksekusi hingga operasi selesai. Block dapat berlangsung dari beberapa milidetik untuk akses disk sampai beberapa menit jika kita menunggu pengguna menekan tombol tertentu.

Server website yang menggunakan I/O pemblokiran tidak akan dapat menangani banyak koneksi dalam utas yang sama. Tiap operasi I/O akan memblokir pemrosesan koneksi lainnya.

Oleh karena itu, untuk mencapai konkurensi, server web memulai utas baru untuk setiap koneksi bersamaan.

Saat utas 'memblokir' untuk operasi I/O, permintaan lain tidak terpengaruh karena permintaan itu memiliki utasnya sendiri yang terpisah.

Makanya, namanya multi-threading.

Lihat contoh di bawah ini

Bagaimana Cara Node.js Mendapatkan Concurrency?

Sayangnya, utas tidak murah dalam hal sumber daya sistem.

Utas menghabiskan memory dan menyebabkan sakelar konteks. Sering kali, sebuah utas mungkin duduk dalam mode diam menunggu beberapa operasi I/O selesai. Ini mengarah pada pemborosan sumber daya.

Cukuplah untuk mengatakan, memiliki utas yang berjalan lama untuk tiap koneksi bukan pendekatan terbaik untuk meningkatkan efisiensi.

Sibuk-Menunggu

Sebagian besar sistem operasi modern mendukung mekanisme yang dikenal sebagai I/O non-blocking.

Tipe I/O ini tidak memblokir eksekusi. Panggilan sistem untuk mengakses sumber daya segera dikembalikan. Jika tidak ada hasil yang ada, fungsi mengembalikan konstanta yang sudah ditentukan sebelumnya. Tak perlu menunggu data untuk dibaca atau ditulis.

Maka bagaimana sebenarnya data diproses?

Jawabannya sibuk-menunggu.

Sibuk-menunggu hanya polling sumber daya secara aktif dalam satu lingkaran sampai mengembalikan beberapa data aktual.

Bagaimana Cara Node.js Mendapatkan Concurrency?

Dengan sibuk menunggu, Anda bisa menggunakan utas yang sama untuk menangani beberapa permintaan I/O.

Tapi algoritma polling juga tidak efisien. Sebagian besar waktu CPU yang berharga terbuang sia-sia untuk mengulang sumber daya yang sebagian besar tidak ada.

Mengapa Node.js tidak bisa menggunakan Multi-Threading

Ada tiga langkah penting dalam proses Event Demultiplexing:

Mengapa Node.js tidak bisa menggunakan Multi-Threading

Bila dibandingkan dengan busy-waiting atau polling, multi-threading ialah pendekatan yang lebih baik untuk mencapai konkurensi. Banyak bahasa pemrograman dan kerangka kerja menggunakan multi-threading dengan sukses.

Tetapi, Node.js tidak dapat menggunakan multi-threading. Ini karena Node.js menggunakan JavaScript dan JavaScript ialah single-threaded.

Lalu apakah tidak ada harapan?

Sebenarnya, ada mekanisme lain untuk mengaktifkan sumber daya non-pemblokiran. Mekanisme ini dikenal sebagai Event Demultiplexing. Anda dapat menyebutnya Layanan Pemberitahuan Acara.

Contoh di bawah menunjukkan ide Event Demultiplexing.

  • Pertama, sumber daya ditambahkan ke daftar pantauan. Setiap sumber daya memiliki operasi terkait seperti baca atau tulis.
  • Daftar pantauan sumber daya ini bersama dengan callback ditetapkan ke Event Demultiplexer. Demultiplexer membuat panggilan sinkron dan pemblokiran untuk setiap kejadian yang dihasilkan dari sumber daya yang diawasi. Ketika demultiplexer akhirnya kembali dari panggilan pemblokiran, ia memiliki serangkaian peristiwa baru yang tersedia untuk diproses.
  • Setiap kejadian yang dikembalikan oleh Event Demultiplexer diproses oleh metode callback aplikasi. Pada titik ini, sumber daya dijamin siap dibaca dan tidak akan diblokir selama operasi. Saat semua peristiwa diproses, demultiplexer akan kembali membuat permintaan pemblokiran untuk rangkaian peristiwa berikutnya.

Proses pengecekan event, memprosesnya, dan memeriksa kembali ini dikenal sebagai Event Loop dan membentuk dasar konkurensi di Node.js. Selain itu, Event Demultiplexer memungkinkan untuk menangani seluruh proses dalam satu utas.

Tidak perlu multi-threading. Tidak perlu sibuk menunggu dan polling. Satu utas dengan waktu idle yang sangat sedikit sudah cukup. Tugas tersebar dari waktu ke waktu alih-alih dibagi di antara banyak utas.

Bagaimana Cara Node.js Mendapatkan Concurrency?

Loop Acara Node.js

Setelah melalui semua penjelasan, saat ini kita bisa membuat model tentang cara kerja loop peristiwa Node.js.

Lihat diagram di bawah ini yang menunjukkan semua cara dalam loop acara.

Bagaimana Cara Node.js Mendapatkan Concurrency?

Mari kita lewat semua cara satu per satu:

  • LANGKAH A — Program membuat permintaan I/O baru dan mengirimkannya ke Event Demultiplexer. Bersamaan dengan request, aplikasi menyediakan handler atau callback. Ini seperti memberi tahu demultiplexer siapa yang harus dihubungi setelah permintaan I/O selesai. Panggilan ke demultiplexer tidak memblokir dan kontrol segera kembali ke aplikasi.
  • LANGKAH B — Demultiplexer Peristiwa menunggu peristiwa dari sumber daya I/O dalam daftar pantauannya. Saat sekumpulan operasi I/O usai, Event Demultiplexer mendorong event yang sesuai ke Antrean Event.
  • LANGKAH C — Event Loop mengulang poin dalam Antrean Acara. Secara tehnis, Event Queue bukan hanya satu antrian melainkan beberapa antrian yang diproses dalam tahapan yang berbeda. Jika tertarik, Anda bisa mempelajari lebih lanjut mengenai antrean Event Loop yang berbeda.
  • LANGKAH D — Untuk setiap event, Event Loop memicu handler. Info tentang handler diberikan ke Event Loop oleh demultiplexer pada LANGKAH B.
  • LANGKAH E — Penangan adalah sisi dari kode aplikasi. Kami mengenal mereka sebagai panggilan balik. Setelah panggilan balik jalan, itu mungkin memberikan kontrol kembali ke Event Loop. Ini dilambangkan dengan jalur E1. Namun, penangan mungkin juga meminta operasi asinkron baru yaitu lajur E2. Lajur E2 menghasilkan operasi baru yang dikirim ke Event Demultiplexer.
  • LANGKAH 6 — Saat Antrean Acara kosong, loop akan memblokir lagi di Demultiplexer Acara dan menunggu siklus yang lain.

Untuk menjelaskan secara singkat, Event Loop menangani I/O dengan memblokir hingga event baru muncul dari sekumpulan sumber daya yang ditonton. Saat acara ada, dia mengirimkan tiap acara ke penangan yang sesuai menggunakan Antrean Acara.

Saat Event Demultiplexer akan kehabisan operasi yang tertunda dan tidak ada event yang tersisa di Event Queue, aplikasi Node.js akan keluar secara otomatis.

Kesimpulan

Node.js bersamaan karena Event Loop. Dan Event Loop dimungkinkan oleh demultiplexer.

Tetapi, sangat sedikit developer yang mengetahui tentang dasar dari Moment Loop. Untuk memberikan kredit pada waktunya, kompleksitas Event Demultiplexer diabstraksi dengan sangat baik sehingga pengembang bisa membangun aplikasi yang berguna dengan Node.js bahkan jika mereka belum pernah mendengar tentang Event Loop.

Meskipun demikian, ada baiknya mengetahui tentang peranan Event Demultiplexer dalam jangka panjang. Ini membantu Anda membuat pilihan yang lebih baik tentang aplikasi Anda.

Bila menurut Anda postingan ini bermanfaat, pertimbangkan untuk membagikannya dengan teman dan kolega.