Node.js, asenkron ve olay güdümlü yapısıyla yüksek performanslı ve ölçeklenebilir uygulamalar geliştirmek için ideal bir platformdur. Node.js'in temelinde, olay döngüsü (event loop) adı verilen bir mekanizma bulunur. Bu mekanizma, non-blocking I/O operasyonlarını yönetir ve farklı kuyruklar aracılığıyla görevlerin yürütülmesini sağlar. Bu makalede, Node.js'deki I/O polling (I/O anketleme) ve check kuyruğunun nasıl çalıştığını ayrıntılı olarak inceleyeceğiz.
Node.js olay döngüsü, görevleri farklı kuyruklara yerleştirir ve bu kuyrukları belirli bir sırayla işler. Temel kuyruklar şunlardır:
Micro Task Kuyruğu: process.nextTick
ve Promise
callback'lerini içerir.
Timer Kuyruğu: setTimeout
ve setInterval
gibi zamanlayıcı tabanlı callback'leri içerir.
I/O Kuyruğu: Tamamlanmış I/O operasyonları için callback'leri içerir.
Check Kuyruğu: setImmediate
callback'lerini içerir.
Bu kuyruklar, belirli bir sırayla işlenir ve her kuyruk, olay döngüsünün farklı bir aşamasında çalıştırılır.
I/O polling, Node.js'in I/O operasyonlarını nasıl yönettiğini anlamak için kritik bir kavramdır. Olay döngüsü, I/O kuyruğuna ulaştığında, tamamlanmış I/O operasyonları için callback'leri kuyruğa eklemek üzere polling yapar. Polling işlemi, I/O işlemlerinin tamamlanıp tamamlanmadığını kontrol eder ve tamamlanmış işlemler için callback'leri kuyruğa ekler.
I/O İşlemleri Başlatılır: Node.js uygulamasında, fs.readFile
, http.get
gibi asenkron I/O fonksiyonları çağrıldığında, bu işlemler işletim sistemi düzeyindeki non-blocking I/O API'lerine iletilir.
Event Loop ve I/O Polling Fazı: Event Loop, I/O polling fazına ulaştığında, tamamlanan I/O işlemlerini kontrol eder. Tamamlanan işlemler için callback'ler, I/O Queue'ya eklenir.
Callback'lerin İşlenmesi: Event Loop, I/O Queue'daki callback'leri sırayla işler. Bu, uygulamanın diğer asenkron işlemlere devam edebilmesi için önemlidir çünkü I/O işlemleri genellikle zaman alıcıdır.
Non-blocking Davranış: Uygulamanın I/O işlemleri tamamlanana kadar bloke olmamasını sağlar.
Etkin Kaynak Kullanımı: I/O işlemleri beklerken, Node.js diğer asenkron görevleri işleyebilir.
Esneklik: Çeşitli türdeki I/O işlemlerini (dosya sistemi, ağ, veritabanı) tek bir model altında yönetir.
Bu süreci daha iyi anlamak için bir örnek inceleyelim:
const fs = require('fs');
process.nextTick(() => {
console.log('nextTick');
});
Promise.resolve().then(() => {
console.log('Promise');
});
setTimeout(() => {
console.log('setTimeout');
}, 0);
fs.readFile(__filename, (err, data) => {
console.log('readFile');
});
setImmediate(() => {
console.log('setImmediate');
});
Yukarıdaki kodda, çeşitli asenkron işlemler gerçekleştirilmiştir: nextTick
, Promise
, setTimeout
, readFile
ve setImmediate
. Bu işlemlerin nasıl sıralandığını inceleyelim:
Micro Task Kuyruğu: process.nextTick
ve Promise
callback'leri önce işlenir.
Timer Kuyruğu: setTimeout
callback'i işlenir.
I/O Kuyruğu: readFile
callback'i işlenir.
Check Kuyruğu: setImmediate
callback'i işlenir.
Micro Task Kuyruğu:
İlk olarak, process.nextTick
callback'i yürütülür ve nextTick
konsola yazdırılır.
Daha sonra, Promise
callback'i yürütülür ve Promise
konsola yazdırılır.
Timer Kuyruğu:
setTimeout
callback'i yürütülür ve setTimeout
konsola yazdırılır.
I/O Kuyruğu:
Olay döngüsü I/O kuyruğuna ulaştığında, readFile
callback'inin hazır olmaması nedeniyle kontrol polling kısmına geçer.
Polling işlemi, readFile
tamamlandığında callback'i kuyruğa ekler.
Ancak, yürütme I/O kuyruğunu geçtiği için callback beklemek zorunda kalır.
Check Kuyruğu:
setImmediate
callback'i yürütülür ve setImmediate
konsola yazdırılır.
Yeni İterasyon:
Yeni bir iterasyon başladığında, I/O kuyruğundaki readFile
callback'i yürütülür ve readFile
konsola yazdırılır.
I/O polling, Node.js'in yüksek performanslı ve non-blocking I/O işlemlerini yönetmesini sağlar. Olay döngüsü, I/O işlemlerini sürekli kontrol ederek tamamlanmış işlemler için callback'leri kuyruğa ekler ve bu sayede diğer görevlerin yürütülmesini engellemez. Bu mekanizma, Node.js'in aynı anda birçok I/O işlemi gerçekleştirebilmesini ve bu işlemler arasında verimli bir şekilde geçiş yapabilmesini sağlar.
Check kuyruğu, olay döngüsünün check aşamasında yürütülen callback'leri içerir. setImmediate
fonksiyonu, bu kuyruğa bir callback eklemek için kullanılır. setImmediate
, mevcut I/O operasyonları tamamlandıktan hemen sonra yürütülmek üzere bir callback ekler. Bu, zamanlamanın kritik olduğu durumlarda kullanışlıdır ve genellikle process.nextTick
ile karşılaştırılır.
setImmediate
ve process.nextTick
arasındaki farklar:
process.nextTick
: Bu fonksiyon, mevcut operasyon tamamlandıktan hemen sonra çalıştırılacak bir callback ekler. Micro task kuyruğunda yer alır ve Promise
callback'leriyle birlikte işlenir.
setImmediate
: Bu fonksiyon, olay döngüsünün check aşamasında çalıştırılacak bir callback ekler. Check kuyruğunda yer alır ve I/O operasyonları tamamlandıktan sonra işlenir.
Node.js'deki I/O polling ve check kuyruğu, olay döngüsünün verimli çalışmasını sağlayan kritik bileşenlerdir. I/O polling, tamamlanmış I/O işlemlerini sürekli kontrol ederken, check kuyruğu setImmediate
gibi callback'leri işlemek için kullanılır. Bu mekanizmalar, Node.js'in asenkron yapısını destekler ve yüksek performanslı uygulamalar geliştirilmesine olanak tanır. Node.js'de I/O polling ve check kuyruğunu anlamak, geliştiricilere daha verimli ve ölçeklenebilir uygulamalar oluşturma konusunda büyük avantaj sağlar.