avatar
·4 dk okuma
Node.js'de I/O Polling

Node.js'de I/O Polling

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.

Olay Döngüsü ve Kuyruklar

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

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 Polling Süreci

  1. 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.

  2. 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.

  3. 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.

I/O Polling'in Avantajları

  • 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:

  1. Micro Task Kuyruğu: process.nextTick ve Promise callback'leri önce işlenir.

  2. Timer Kuyruğu: setTimeout callback'i işlenir.

  3. I/O Kuyruğu: readFile callback'i işlenir.

  4. Check Kuyruğu: setImmediate callback'i işlenir.

i/o polling image

Olay Döngüsünün Çalışma Süreci

  1. 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.

  2. Timer Kuyruğu:

    • setTimeout callback'i yürütülür ve setTimeout konsola yazdırılır.

  3. 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.

  4. Check Kuyruğu:

    • setImmediate callback'i yürütülür ve setImmediate konsola yazdırılır.

  5. 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'in Önemi

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 ve setImmediate

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.

Sonuç

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.