Node.js'de engellemeyen veya eşzamansız G / Ç nedir?


136

Sunucu Tarafı Javascript motorları bağlamında, engellemeyen G / Ç veya eşzamansız G / Ç nedir? Bunun Java sunucu tarafı uygulamalarına göre bir avantaj olarak görüldüğünü görüyorum.


3
Bu kavramı anlamak için tarayıcı ortamındaki komut dosyası etiketlerini düşünmek faydalıdır. Zakas'ın bu konuda harika bir makalesi var - ilk birkaç bölüm engelleme kavramını açıklamak için yeterli olmalı: nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

Yanıtlar:


317

Senkron ve Asenkron

Senkron yürütme genellikle kod yürütmeyi sırayla gerçekleştirir. Zaman uyumsuz yürütme, kodda göründüğü sırada çalışmayan yürütmeyi ifade eder. Aşağıdaki örnekte, eşzamanlı işlem uyarıların sırayla tetiklenmesine neden olur. Zaman uyumsuz işleminde alert(2), sanki ikinci yürütülmüş gibi görünüyor, değil.

Senkronize: 1,2,3

alert(1);
alert(2);
alert(3);

Eşzamansız: 1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);

Engelleme ve Engellememe

Engelleme, işlem bitene kadar daha fazla yürütmeyi engelleyen işlemleri ifade eder. Engellememe, yürütmeyi engellemeyen kodu belirtir. Verilen örnekte, localStorageokumayı yürütmeyi durdurduğu için bir engelleme işlemidir. Öte yandan, yürütmeden fetchduraklamadığı için tıkanmayan bir işlemdir alert(3).

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);

Avantajları

Engellemeyen, eşzamansız işlemlerin bir avantajı, tek bir CPU'nun yanı sıra bellek kullanımını en üst düzeye çıkarabilmenizdir.

Senkron, engelleme örneği

Eşzamanlı, engelleme işlemlerine örnek olarak Java veya PHP gibi bazı web sunucularının G / Ç veya ağ isteklerini nasıl ele aldığı gösterilebilir. Kodunuz bir dosyadan veya veritabanından okursa, kodunuz yürütüldükten sonra her şeyi "engeller". Bu dönemde, makineniz hiçbir şey yapmayan bir iş parçacığının belleğini ve işlem süresini tutar .

Bu iş parçacığı dururken diğer istekleri karşılamak için yazılımınıza bağlıdır. Çoğu sunucu yazılımının yaptığı, ek istekleri karşılamak için daha fazla iş parçacığı oluşturmaktır. Bu, daha fazla bellek tüketimi ve daha fazla işlem gerektirir.

Eşzamansız, engellemeyen örnek

Düğümde yapılanlar gibi eşzamansız, engellemeyen sunucular tüm isteklere hizmet vermek için yalnızca bir iş parçacığı kullanır. Bu, Düğüm örneğinin tek bir iş parçacığından en iyi şekilde yararlandığı anlamına gelir. İçerik oluşturucular bunu G / Ç ve ağ işlemlerinin darboğaz olduğu düşüncesiyle tasarladılar.

İstekler sunucuya ulaştığında, her seferinde bir tanesine hizmet verilir. Ancak, hizmet verilen kodun DB'yi sorgulaması gerektiğinde, geri aramayı ikinci bir kuyruğa gönderir ve ana iş parçacığı çalışmaya devam eder (beklemez). Şimdi DB işlemi tamamlandığında ve geri döndüğünde, karşılık gelen geri arama ikinci kuyruktan çıkarıldı ve yürütülmeyi bekleyen üçüncü bir kuyrukta kuyruğa girdi. Motor başka bir şeyi yürütme şansı elde ettiğinde (yürütme yığını boşaltıldığında olduğu gibi), üçüncü kuyruktan bir geri arama alır ve yürütür.


5
PHP'de Engelleme altında 2. paragrafınızı anladığımdan emin değilim . "PHP normalde IO üzerinde engelleme yapsa da, işletim sisteminin otomatik olarak IO işlemlerini işlediğinden değil" diyor musunuz? Veya PHP'nin her sorun için otomatik olarak yeni bir iş parçacığı oluşturduğundan, engellenen bir isteğin tüm PHP ortamını durdurmaması nedeniyle bunun PHP'de bir sorun olmadığını mı söylüyorsunuz? (Ben ikincisini tahmin ediyorum ..)
dcow

6
Bu sonuncusu.
Joseph

2
Eğer ikincisi demekse, engellemeyen I / O PHP'nin (reaktifPHP veya başka bir şey gibi) engelleme üzerindeki avantajları. hala karıştırmayın
Sunu Pinasthika Fajar

5
@CharlieParker Evet. Zaman uyumsuz işlem kodunuza paralel çalışır. Ancak, zaman uyumsuz işlemin sonuçlarına "geri döner" geri çağrısı, ana kod meşgul olmadığında ana kodda yürütmek için sıraya alınır.
Joseph

2
@CharlieParker İşte asenkron mekanizmanın içleri hakkında daha fazla bilgi veren bir yazı .
Joseph

7
var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2

Kod örneği

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.