Node.js İle Çoklu İşlemci Kullanımı İçin Cluster Yapılandırması Nasıl Yapılır?

Node.js İle Çoklu İşlemci Kullanımı İçin Cluster Yapılandırması Nasıl Yapılır?
Node.js İle Çoklu İşlemci Kullanımı İçin Cluster Yapılandırması Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Uygulamaya başlamadan önce sisteminizde Node.js'in güncel bir sürümünün (LTS 22.x veya üzeri önerilir) kurulu olduğundan emin olmalısınız. Cluster modülü, Node.js çekirdeği ile birlikte geldiği için harici bir paket kurmanıza gerek yoktur.

  • Node.js 22.x veya daha yeni bir sürüm.
  • İşletim sistemi seviyesinde süreç yönetimi hakkında temel bilgi.
  • Proje dizininizi oluşturmak için bir terminal veya komut satırı arayüzü.

Çalışma ortamınızı doğrulamak için terminalinize node -v komutunu yazarak sürümünüzü kontrol edebilirsiniz. Eğer sürümünüz eski ise, nvm (Node Version Manager) kullanarak güncel sürüme geçiş yapmanız önerilir.

Cluster Modülünün Mantığı ve Çalışma Prensibi

Cluster modülü, ana bir süreç (Master Process) ve bu ana süreç tarafından yönetilen alt süreçler (Worker Processes) mantığıyla çalışır. Master süreç, gelen bağlantıları dinler ve bunları uygun olan worker süreçlerine dağıtır. Bu sayede her bir worker, kendi bellek alanına ve CPU çekirdeğine sahip olur.

Aşağıdaki temel örnekte, sistemdeki CPU çekirdek sayısını tespit ederek her çekirdek için bir worker oluşturacağız.

const cluster = require('node:cluster');
const http = require('node:http');
const os = require('node:os');

if (cluster.isPrimary) {
  const numCPUs = os.cpus().length;
  console.log(`Master süreç ${process.pid} çalışıyor.`);

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} kapandı.`);
  });
} else {
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Merhaba, Cluster dünyası!\n');
  }).listen(8000);
  console.log(`Worker ${process.pid} başladı.`);
}

Bu kodda cluster.isPrimary kontrolü ile ana sürecin worker süreçlerini oluşturmasını sağlıyoruz. os.cpus().length fonksiyonu, işlemcinizdeki mantıksal çekirdek sayısını döndürür, böylece donanımınıza uygun sayıda süreç başlatılır.

Worker Süreçlerinin Yönetimi ve Hata Toleransı

Üretim ortamında bir worker sürecinin çökmesi, uygulamanın tamamının durmasına neden olmamalıdır. Cluster yapısında, çöken bir worker'ı tespit edip yerine yenisini başlatmak (respawn) sistemin sürekliliği için kritiktir.

cluster.on('exit', (worker, code, signal) => {
  console.error(`Worker ${worker.process.pid} çöktü. Yenisi başlatılıyor...`);
  cluster.fork();
});

Yukarıdaki kod bloğu, exit olayını dinleyerek herhangi bir worker kapandığında otomatik olarak yeni bir tane oluşturur. Bu, uygulamanızın kesintisiz çalışmasını sağlayan "self-healing" (kendi kendini iyileştirme) mekanizmasının temelidir.

Cluster Yapılandırmasında İletişim ve Veri Paylaşımı

Worker süreçleri birbirinden bağımsız bellek alanlarına sahiptir. Bir worker'da tanımlanan değişken, diğerine doğrudan aktarılamaz. Süreçler arası iletişim (IPC) için worker.send() ve process.on('message') yöntemleri kullanılır.

// Master süreçten worker'a mesaj gönderimi
if (cluster.isPrimary) {
  const worker = cluster.fork();
  worker.send({ type: 'CONFIG', data: 'Önemli Ayarlar' });
} else {
  process.on('message', (msg) => {
    if (msg.type === 'CONFIG') {
      console.log('Worker ayarları aldı:', msg.data);
    }
  });
}

Bu yöntem, özellikle yapılandırma verilerini dağıtmak veya merkezi bir loglama sistemi kurmak için oldukça kullanışlıdır. Ancak, çok yüksek frekanslı veri alışverişi performans kaybına yol açabileceği için dikkatli kullanılmalıdır.

Cluster Yöntemlerinin Karşılaştırması

Node.js uygulamalarını ölçeklendirmek için farklı yöntemler mevcuttur. Aşağıdaki tablo, Cluster modülü ile diğer yaklaşımları kıyaslamaktadır.

Yöntem Avantaj Dezavantaj
Cluster Modülü Aynı port, kolay yönetim Bellek kullanımı artar
PM2 Process Manager Otomatik izleme, sıfır kesinti Harici bağımlılık gerektirir
Docker/Kubernetes İzole ortamlar, yüksek ölçek Karmaşık yapılandırma

Üretim Ortamında Güvenlik ve Performans

Kritik Uyarı: Cluster yapısı kullanırken, her worker'ın ayrı bir süreç olduğunu unutmayın. Hassas verileri (session bilgileri, şifreler vb.) bellekte tutmak yerine Redis gibi harici bir "state store" kullanın. Aksi takdirde, kullanıcı bir istekte farklı bir worker'a yönlendirildiğinde oturum verilerine erişemez.

Ayrıca, güvenlik için helmet gibi kütüphaneleri kullanarak HTTP başlıklarını korumalı, SQL injection riskine karşı ise her zaman parametreli sorgular (prepared statements) kullanmalısınız.

// Güvenli bir şekilde veritabanı sorgusu örneği
const query = 'SELECT * FROM users WHERE id = ?';
db.execute(query, [userId], (err, results) => {
  if (err) throw err;
  console.log(results);
});

Sıkça Sorulan Sorular

Cluster modülü her zaman performans artışı sağlar mı?

Hayır, I/O ağırlıklı uygulamalarda (örneğin veritabanı okuma/yazma) Node.js zaten oldukça verimlidir. Cluster, özellikle CPU yoğunluklu (şifreleme, görsel işleme, karmaşık hesaplamalar) uygulamalarda ciddi performans artışı sağlar.

Bir worker süreci çökerse diğerleri etkilenir mi?

Hayır, Cluster modülünün en büyük avantajı izolasyondur. Bir worker'daki hata, diğer süreçleri ve ana süreci etkilemez.

Cluster modülü yerine neden PM2 kullanmalıyım?

PM2, Cluster modülünü arka planda kullanan profesyonel bir süreç yöneticisidir. Log yönetimi, otomatik yeniden başlatma, izleme (monitoring) ve "zero-downtime" (sıfır kesinti) ile güncelleme gibi özellikleri hazır sunduğu için üretim ortamında standarttır.

Aynı portu birden fazla süreç nasıl dinleyebilir?

Node.js Cluster modülü, ana süreçte bir TCP sunucusu oluşturur ve gelen bağlantıları dahili bir yük dengeleyici (load balancer) aracılığıyla worker süreçlerine dağıtır. Bu yüzden sadece ana süreç portu dinliyor gibi görünür.

Bellek kullanımı nasıl optimize edilir?

Her worker kendi bellek alanını kullandığı için, çok fazla worker başlatmak RAM tüketimini hızla artırır. İdeal olan, CPU çekirdek sayınız kadar worker başlatmaktır.

Sorumluluk Reddi: Bu makalede yer alan kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce uygulamanızın özel ihtiyaçlarına göre güvenlik testlerini yapmalı ve uygun yapılandırma dosyalarını (environment variables) kullanmalısınız.

Cluster Ortamında Hata Ayıklama ve İzleme Stratejileri

Çoklu süreç mimarisine geçiş yaptığınızda, geleneksel hata ayıklama yöntemleri (debug) yetersiz kalabilir. Her bir worker süreci kendi bellek alanına sahip olduğundan, tek bir süreçteki hatayı yakalamak için merkezi bir loglama mekanizması kurmanız şarttır. Worker süreçlerinden gelen çıktıları birleştirmek ve izlemek için aşağıdaki stratejileri uygulayabilirsiniz.

Worker Süreçleri İçin Merkezi Loglama

Her worker'ın standart çıktısını (stdout/stderr) tek bir dosyaya veya merkezi bir log sunucusuna yönlendirmek, hata takibini kolaylaştırır. Aşağıdaki örnek, her worker'ın kendi ID'sini log mesajlarına ekleyerek izlenebilirliği nasıl artırabileceğinizi gösterir:

const cluster = require('cluster');
const fs = require('fs');
const path = require('path');

if (cluster.isWorker) {
    const logStream = fs.createWriteStream(path.join(__dirname, 'worker.log'), { flags: 'a' });
    
    // Console çıktılarını dosyaya yönlendir
    process.stdout.write = process.stderr.write = logStream.write.bind(logStream);
    
    console.log(`Worker ${process.pid} başlatıldı.`);
    
    process.on('uncaughtException', (err) => {
        console.error(`Worker ${process.pid} hata yakaladı: ${err.message}`);
        process.exit(1);
    });
}

Cluster Uygulamalarında Performans Testi

Cluster yapısının uygulamanıza sağladığı gerçek katkıyı ölçmek için yük testleri yapmanız gerekir. Autocannon veya Apache Benchmark (ab) gibi araçlar, eşzamanlı istek sayısını artırarak CPU çekirdeklerinizin ne kadar verimli kullanıldığını görmenizi sağlar.

Metrik Açıklama
Requests/sec Saniyedeki toplam istek sayısı (Cluster ile artmalı).
Latency İsteklerin yanıt süresi (Yüksek yük altında stabil kalmalı).
CPU Usage Tüm çekirdeklerin dengeli dağılımı (Load balancing kontrolü).

İleri Seviye İpuçları: Sticky Sessions ve Socket.io

Eğer uygulamanızda WebSocket (Socket.io gibi) kullanıyorsanız, standart Cluster modülü "sticky sessions" (yapışkan oturumlar) desteğine ihtiyaç duyar. WebSocket bağlantıları ilk el sıkışma (handshake) aşamasında HTTP üzerinden gerçekleşir ve ardından uzun süreli bir bağlantıya dönüşür. Eğer yük dengeleyici bağlantıyı farklı bir worker'a yönlendirirse, bağlantı kopar.

Bu sorunu çözmek için socket.io-redis adaptörünü kullanabilir veya yük dengeleyici (Nginx gibi) seviyesinde IP tabanlı yönlendirme yapabilirsiniz. Aşağıdaki yapılandırma, Socket.io'nun çoklu süreçlerde nasıl destekleneceğine dair temel bir yaklaşımdır:

const { createAdapter } = require("@socket.io/redis-adapter");
const { createClient } = require("redis");

// Worker içerisinde Redis adaptörünü yapılandırın
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

// Bu sayede farklı worker'lar üzerindeki istemciler 
// birbirleriyle mesajlaşabilir.

Bu yaklaşım, uygulamanızın sadece HTTP isteklerini değil, gerçek zamanlı veri akışlarını da ölçeklenebilir bir şekilde yönetmesini sağlar. Unutmayın, Redis kullanımı ek bir ağ katmanı getirse de, çoklu süreç mimarisinde veri tutarlılığını sağlamak için en güvenilir yöntemdir.

Sonuç

Node.js ile Cluster yapılandırması, uygulamanızın ölçeklenebilirliğini artırmak için temel bir adımdır. Bu rehberde, süreçlerin nasıl oluşturulacağını, yönetileceğini ve birbirleriyle nasıl iletişim kuracağını öğrendiniz. Bir sonraki adım olarak, PM2 gibi süreç yöneticilerini inceleyebilir ve uygulamanızı Docker konteynerleri içerisinde nasıl daha güvenli hale getireceğinizi araştırabilirsiniz. Başarılı kodlamalar dilerim.

Bu yazıya tepkinizi paylaşın:
Emre Güneş

Teknik çözümler ve ev gereçleri kullanımı konusunda deneyimli bir editörüm. Kullanıcı hatalarını minimize eden, yalın ve çözüm odaklı rehberler hazırlıyorum.

Yorumlar (0)

Yorum Yaz