Düğümün tamamen farklı bir paradigması vardır ve doğru bir şekilde yakalandığında, problem çözmenin bu farklı yolunu görmek daha kolaydır. Bir Node uygulamasında (1) asla birden fazla iş parçacığına ihtiyacınız olmaz çünkü aynı şeyi yapmanın farklı bir yolu vardır. Birden çok işlem oluşturursunuz; ancak, örneğin Apache Web Sunucusunun Prefork mpm'nin yaptığından çok farklıdır.
Şimdilik, sadece bir CPU çekirdeğimiz olduğunu düşünelim ve biraz iş yapmak için bir uygulama (Düğüm yolunda) geliştireceğiz. Bizim işimiz, içeriği bayt bayt üzerinde çalışan büyük bir dosyayı işlemektir. Yazılımımızın en iyi yolu, işe dosyanın başından başlamak, bayt bayt sonuna kadar takip etmektir.
- Hey, Hasan, galiba sen ya çaylaksın ya da büyükbabamın zamanından kalma çok eski bir okulsun !!! Neden bazı konular oluşturup daha hızlı hale getirmiyorsunuz?
- Sadece bir CPU çekirdeğimiz var.
-- Ne olmuş yani? Biraz ip yarat adamım, daha hızlı yap!
- Böyle çalışmıyor. İplikler oluşturursam, daha yavaş yapacağım. Çünkü iş parçacıkları arasında geçiş yapmak, onlara sadece bir süre vermek için sisteme çok fazla ek yük ekleyeceğim ve sürecimin içinde bu iş parçacıkları arasında iletişim kurmaya çalışacağım. Tüm bu gerçeklere ek olarak, tek bir işi paralel olarak yapılabilecek birden fazla parçaya nasıl böleceğimi de düşünmem gerekecek.
- Tamam tamam, fakir olduğunu görüyorum. Bilgisayarımı kullanalım, 32 çekirdeği var!
- Vay canına, harikasın sevgili dostum, çok teşekkür ederim. Bunu takdir ediyorum!
Sonra işe geri dönüyoruz. Zengin dostumuz sayesinde artık 32 cpu çekirdeğimiz var. Uymamız gereken kurallar az önce değişti. Şimdi bize verilen tüm bu serveti kullanmak istiyoruz.
Birden çok çekirdek kullanmak için, çalışmamızı paralel olarak halledebileceğimiz parçalara ayırmanın bir yolunu bulmalıyız. Düğüm olmasaydı, bunun için evreleri kullanırdık; Her cpu çekirdeği için bir tane olmak üzere 32 iş parçacığı. Ancak Node'umuz olduğu için 32 Node süreci oluşturacağız.
İş parçacığı, Düğüm süreçlerine iyi bir alternatif olabilir, hatta daha iyi bir yol olabilir; ancak yalnızca işin zaten tanımlandığı ve işin nasıl yapılacağı konusunda tam kontrole sahip olduğumuz belirli bir işte. Bunun dışında, işin kontrolümüzün olmadığı bir şekilde dışarıdan geldiği ve olabildiğince çabuk cevap vermek istediğimiz her türlü problem için Node'un yolu tartışmasız üstündür.
- Hey, Hasan, hala tek iş parçacığı mı çalışıyorsun? Senin sorunun ne adamım? Sana istediğini verdim. Artık bahanen yok. İş parçacığı oluşturun, daha hızlı çalışmasını sağlayın.
- Çalışmayı parçalara ayırdım ve her süreç bu parçalardan biri üzerinde paralel olarak çalışacak.
- Neden konu oluşturmuyorsunuz?
- Üzgünüm, kullanılabilir olduğunu sanmıyorum. İstersen bilgisayarını alabilir misin?
- Hayır tamam, ben iyiyim, neden ipleri kullanmadığını anlamıyorum?
- Bilgisayar için teşekkürler. :) Çalışmayı zaten parçalara ayırdım ve bu parçalar üzerinde paralel olarak çalışmak için süreçler oluşturuyorum. Tüm CPU çekirdekleri tam olarak kullanılacaktır. Bunu süreçler yerine iş parçacıklarıyla yapabilirim; ancak Node'un yolu bu ve patronum Parth Thakkar benden Node'u kullanmamı istiyor.
- Tamam, başka bir bilgisayara ihtiyacın olursa haber ver. : p
32 yerine 33 işlem oluşturursam, işletim sisteminin zamanlayıcısı bir iş parçacığını duraklatacak, diğerini başlatacak, birkaç döngüden sonra duraklatacak, diğerini yeniden başlatacak ... Bu gereksiz ek yük. Onu istemiyorum. Aslında, 32 çekirdekli bir sistemde, tam olarak 32 işlem oluşturmak bile istemem, 31 daha iyi olabilir . Çünkü bu sistemde çalışacak olan sadece benim uygulamam değil. Diğer şeyler için biraz yer bırakmak iyi olabilir, özellikle de 32 odamız varsa.
İşlemcileri CPU yoğun görevler için tam olarak kullanma konusunda artık aynı sayfada olduğumuza inanıyorum .
- Hmm, Hasan, seninle biraz alay ettiğim için üzgünüm. Şimdi seni daha iyi anladığıma inanıyorum. Yine de açıklamaya ihtiyacım olan bir şey var: Yüzlerce iş parçacığı çalıştırmanın tüm vızıltıları nedir? Her yerde iş parçacığı oluşturmanın çatal işlemlerinden çok daha hızlı ve aptal olduğunu okudum. İş parçacıkları yerine süreçleri çatallıyorsunuz ve Node ile elde edeceğiniz en yüksek değer olduğunu düşünüyorsunuz. O halde Node bu tür işler için uygun değil mi?
- Endişelenme, ben de iyiyim. Herkes böyle şeyler söylüyor, bu yüzden duymaya alışkın olduğumu düşünüyorum.
-- Yani? Düğüm bunun için iyi değil mi?
- Düğüm, iş parçacıkları da iyi olabilse de bunun için mükemmel derecede iyidir. İş parçacığı / süreç oluşturma ek yüküne gelince; çok tekrarladığınız şeylerde her milisaniye önemlidir. Ancak ben sadece 32 işlem oluşturuyorum ve çok az zaman alacak. Sadece bir kez olacak. Hiç fark etmeyecek.
- O halde ne zaman binlerce iş parçacığı oluşturmak istiyorum?
- Asla binlerce iş parçacığı oluşturmak istemezsiniz. Ancak, HTTP isteklerini işleyen bir web sunucusu gibi, dışarıdan gelen işleri yapan bir sistemde; her istek için bir iş parçacığı kullanıyorsanız, çoğu iş parçacığı oluşturursunuz.
- Yine de düğüm farklı mı? Sağ?
-- Evet kesinlikle. Node'un gerçekten parladığı yer burasıdır. Bir iş parçacığı bir işlemden çok daha hafifse, bir işlev çağrısı da bir iş parçacığından çok daha hafiftir. Düğüm, iş parçacığı oluşturmak yerine işlevleri çağırır. Bir web sunucusu örneğinde, gelen her istek bir işlev çağrısına neden olur.
-- Hmm, ilginç; ancak birden fazla iş parçacığı kullanmıyorsanız aynı anda yalnızca bir işlevi çalıştırabilirsiniz. Web sunucusuna aynı anda çok sayıda istek ulaştığında bu nasıl çalışır?
- İşlevlerin nasıl çalıştığı konusunda tamamen haklısınız, ikisi birden paralel değil. Demek istediğim, tek bir işlemde, bir seferde yalnızca bir kod kapsamı çalışıyor. İşletim Sistemi Zamanlayıcı, sürecimizdeki başka bir iş parçacığına değil, başka bir işleme zaman vermek için işlemi duraklatmadığı sürece, bu işlevi durdurmaz ve başka bir işleme geçmez. (2)
- O halde bir süreç bir seferde 2 isteği nasıl işleyebilir?
- Sistemimiz yeterli kaynağa (RAM, Ağ, vb.) Sahip olduğu sürece, bir süreç bir seferde on binlerce isteği işleyebilir. Bu işlevlerin nasıl çalıştığı ANAHTAR FARK.
- Hmm, şimdi heyecanlanmalı mıyım?
- Belki :) Düğüm, kuyruk üzerinde bir döngü çalıştırır. Bu kuyrukta bizim işlerimiz, yani gelen talepleri işlemeye başladığımız aramalar var. Buradaki en önemli nokta, işlevlerimizi çalışacak şekilde tasarlama şeklimizdir. Bir talebi işleme koymaya başlamak ve arayanı işi bitirene kadar bekletmek yerine, kabul edilebilir miktarda iş yaptıktan sonra işlevimizi hızlı bir şekilde sonlandırıyoruz. Başka bir bileşenin biraz iş yapması ve bize bir değer vermesini beklememiz gereken bir noktaya geldiğimizde, bunu beklemek yerine, işin geri kalanını kuyruğa ekleyerek işlevimizi bitiririz.
- Kulağa çok mu karmaşık geliyor?
- Hayır hayır, karmaşık gelebilirim; ancak sistemin kendisi çok basit ve çok mantıklı.
Şimdi, bu iki geliştirici arasındaki diyaloğu alıntı yapmayı bırakmak ve bu işlevlerin nasıl çalıştığına dair son hızlı bir örnekten sonra cevabımı bitirmek istiyorum.
Bu şekilde, OS Scheduler'ın normalde yapacağı şeyi yapıyoruz. Çalışmamızı bir noktada durdururuz ve sıramızı tekrar alana kadar diğer işlev çağrılarının (çok iş parçacıklı bir ortamdaki diğer evreler gibi) çalışmasına izin veririz. Bu, işi sistemdeki her iş parçacığına sadece zaman vermeye çalışan OS Scheduler'a bırakmaktan çok daha iyidir. Neyi yaptığımızı OS Scheduler'ın yaptığından çok daha iyi biliyoruz ve durmamız gerektiğinde durmamız bekleniyor.
Aşağıda, veriler üzerinde biraz çalışma yapmak için bir dosyayı açıp okuduğumuz basit bir örnek verilmiştir.
Senkron Yol:
Open File
Repeat This:
Read Some
Do the work
Eşzamansız Yol:
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
Gördüğünüz gibi, fonksiyonumuz sistemden bir dosyayı açmasını istiyor ve açılmasını beklemiyor. Dosya hazır olduktan sonra sonraki adımları sağlayarak kendini tamamlar. Geri döndüğümüzde, Node kuyrukta diğer fonksiyon çağrılarını çalıştırır. Tüm fonksiyonların üzerinden geçtikten sonra, olay döngüsü bir sonraki sıraya geçer ...
Özetle, Node'un çok iş parçacıklı geliştirmeden tamamen farklı bir paradigması vardır; ancak bu, eksik olduğu anlamına gelmez. Eşzamanlı bir iş için (işleme sırasına ve yöntemine karar verebileceğimiz), çok iş parçacıklı paralelliğin yanı sıra çalışır. Sunucuya yapılan istekler gibi dışarıdan gelen bir iş için, basitçe üstündür.
(1) C / C ++ gibi diğer dillerde kitaplıklar oluşturmadığınız sürece, bu durumda işleri bölmek için yine de iş parçacıkları oluşturmazsınız. Bu tür işler için, biri gerçek işi yaparken diğeri Düğüm ile iletişime devam edecek iki iş parçacığına sahipsiniz.
(2) Aslında, her Node işleminin ilk dipnotta bahsettiğim aynı nedenlerle birden fazla iş parçacığı vardır. Ancak bu, benzer işler yapan 1000 iş parçacığına benzemez. Bu ekstra iş parçacıkları, IO olaylarını kabul etmek ve süreçler arası mesajlaşmayı yönetmek gibi şeyler içindir.
GÜNCELLEME (Yorumlarda iyi bir soruya yanıt olarak)
@Mark, yapıcı eleştirileriniz için teşekkür ederim. Düğüm paradigmasında, kuyruktaki diğer tüm çağrılar birbiri ardına çalışacak şekilde tasarlanmadıkça işlenmesi çok uzun süren işlevlere asla sahip olmamalısınız. Hesaplama açısından pahalı görevler söz konusu olduğunda, resme tam olarak bakarsak, bunun "iş parçacıkları veya süreçler kullanmalı mıyız?" Sorusu olmadığını görürüz. ancak "Bu görevleri, sistemde birden fazla CPU çekirdeği kullanarak paralel olarak çalıştırabileceğimiz alt görevlere dengeli bir şekilde nasıl bölebiliriz?" Diyelim ki 8 çekirdekli bir sistemde 400 video dosyası işleyeceğiz. Bir seferde bir dosyayı işlemek istiyorsak, aynı dosyanın farklı kısımlarını işleyecek bir sisteme ihtiyacımız var, bu durumda, belki, çok iş parçacıklı tek işlemli bir sistemin oluşturulması daha kolay ve daha da verimli olacaktır. Durum paylaşımı / iletişimi gerekli olduğunda birden fazla işlem çalıştırarak ve aralarında mesajlar geçirerek bunun için Node'u kullanmaya devam edebiliriz. Daha önce de söylediğim gibi, Node ile çok süreçli bir yaklaşımbu tür görevlerde çok parçalı bir yaklaşımın yanı sıra ; ama bundan daha fazlası değil. Yine, daha önce de söylediğim gibi, Düğümün parladığı durum, bu görevlerin sisteme birden çok kaynaktan girdi olarak gelmesidir, çünkü birçok bağlantıyı aynı anda tutmak, bağlantı başına iş parçacığı veya bağlantı başına işlemle karşılaştırıldığında Düğümde çok daha hafiftir. sistemi.
setTimeout(...,0)
Aramalara gelince ; bazen, kuyruktaki çağrıların işlem paylarına sahip olmasına izin vermek için zaman alıcı bir görev sırasında ara vermek gerekebilir. Görevleri farklı şekillerde bölmek sizi bunlardan kurtarabilir; ama yine de, bu gerçekten bir hack değil, sadece olay kuyruklarının çalışma şeklidir. Ayrıca, process.nextTick
bu amaç için kullanmak çok daha iyidir, çünkü kullandığınızda setTimeout
, geçen zamanın hesaplanması ve kontrol edilmesi gerekli olacaktır, ancak process.nextTick
gerçekten istediğimiz şey budur: "Hey görev, sıranın sonuna geri dön, payını kullandın! "