Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!
[NODE JS] Cluster Modülü ile Çoklu Process
Bir Node.js sunucusu varsayılan olarak tek bir CPU çekirdeği kullanır. Sunucunuzda 8 çekirdek varsa, 7 tanesi boşta kalır. Bu israf değil mi? İşte cluster modülü tam olarak bu sorunu çözer. Master süreç, CPU çekirdeği sayısı kadar worker süreç oluşturur ve gelen istekleri bu worker'lara dağıtır. Ben production ortamında cluster kullanmaya başladığımda, aynı donanımla 3-4 kat daha fazla istek karşılayabilir hale geldim.
Cluster modülü, child_process.fork üzerine kurulmuş bir soyutlama katmanıdır. Ama ondan çok daha kullanışlıdır çünkü HTTP sunucu portunu paylaşma mekanizması içerir. Normalde aynı portu iki farklı süreç dinleyemez, ama cluster modülü bu sorunu round-robin yük dengeleme ile çözer. Linux ve macOS'ta round-robin varsayılan stratejidir. Windows'ta ise işletim sistemi seviyesinde dağıtım yapılır.
Cluster mimarisinde bir master süreç ve birden fazla worker süreç vardır. Master süreç genellikle iş mantığı çalıştırmaz, sadece worker'ları yönetir. İstekleri karşılayan worker'lardır. Bir worker çökerse, master bunu algılar ve yerine yeni bir worker başlatabilir. Bu sayede uygulamanız son derece dayanıklı hale gelir. Tek bir worker'ın çökmesi, diğer worker'ları etkilemez.
Cluster kullanırken dikkat etmeniz gereken en önemli konu, durumun (state) paylaşımıdır. Her worker ayrı bir süreçtir ve kendi bellek alanına sahiptir. Yani bir worker'da oturuma bir veri yazdığınızda, diğer worker bunu göremez. Bu sorunu çözmek için Redis gibi harici bir oturum deposu kullanmanız gerekir. Veritabanı bağlantıları, dosya kilitleri, zamanlayıcılar gibi paylaşılan kaynaklar da dikkatle yönetilmelidir.
Pratikte cluster modülünü doğrudan kullanmak yerine PM2 gibi process manager'ları tercih eden geliştiriciler çoğunluktadır. PM2, cluster modülünü dahili olarak kullanır ama üzerine bir sürü kolaylık ekler: otomatik yeniden başlatma, sıfır kesinti güncellemesi, log yönetimi, kaynak izleme. Ama cluster modülünün nasıl çalıştığını anlamak, PM2'yi daha verimli kullanmanızı sağlar.
Worker süreçler arası iletişim IPC kanalı üzerinden gerçekleşir. Master'dan worker'a veya worker'dan master'a mesaj gönderebilirsiniz. Ancak worker'dan worker'a doğrudan mesaj gönderemezsiniz; master üzerinden geçmeniz gerekir. Bu iletişim mekanizması, görev dağıtımı ve koordinasyon için kullanılabilir.
Bir diğer önemli konu da graceful shutdown'dur. Sunucuyu kapatırken mevcut isteklerin tamamlanmasını beklemeniz gerekir. Her worker'a sırayla kapanma sinyali gönderir, aktif isteklerini bitirmesini bekler ve ardından yeni worker başlatırsınız. Bu strateji, sıfır kesinti ile güncelleme yapmanızı sağlar.
Cluster kullanırken bellek tüketimini de göz önünde bulundurmalısınız. Her worker ayrı bir V8 instance çalıştırır ve kendi bellek alanına sahiptir. 4 worker ile çalışıyorsanız, tek worker'ın bellek kullanımının yaklaşık 4 katı bellek tüketirsiniz. Bu yüzden sunucunuzun bellek kapasitesine göre worker sayısını ayarlamanız önemlidir.
JavaScript:
// ==============================
// Cluster Modülü Temel Kullanımı
// ==============================
const cluster = require('cluster');
const http = require('http');
const os = require('os');
const CPU_SAYISI = os.cpus().length;
const PORT = 3000;
if (cluster.isMaster) {
console.log(`Master süreç başlatıldı. PID: ${process.pid}`);
console.log(`CPU çekirdek sayısı: ${CPU_SAYISI}`);
console.log(`${CPU_SAYISI} adet worker oluşturuluyor...
`);
// Her çekirdek için bir worker oluştur
for (let i = 0; i < CPU_SAYISI; i++) {
const worker = cluster.fork();
console.log(`Worker ${worker.id} başlatıldı. PID: ${worker.process.pid}`);
}
// Worker çöktüğünde yenisini başlat
cluster.on('exit', (worker, code, signal) => {
console.error(`Worker ${worker.id} kapandı. Kod: ${code}, Sinyal: ${signal}`);
if (code !== 0) {
console.log('Yeni worker başlatılıyor...');
const yeniWorker = cluster.fork();
console.log(`Yeni Worker ${yeniWorker.id} başlatıldı. PID: ${yeniWorker.process.pid}`);
}
});
// Worker'lardan gelen mesajları dinle
for (const id in cluster.workers) {
cluster.workers[id].on('message', (mesaj) => {
console.log(`Worker ${id} mesaj gönderdi:`, mesaj);
});
}
// Periyodik sağlık kontrolü
setInterval(() => {
const aktifWorkerlar = Object.keys(cluster.workers).length;
console.log(`Aktif worker sayısı: ${aktifWorkerlar}`);
}, 30000);
} else {
// Worker süreç kodu
const sunucu = http.createServer((req, res) => {
// İstek işleme simülasyonu
const baslangic = Date.now();
if (req.url === '/agir-islem') {
// CPU yoğun işlem simülasyonu
let toplam = 0;
for (let i = 0; i < 10000000; i++) {
toplam += Math.sqrt(i);
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
sonuc: toplam,
workerPid: process.pid,
sure: Date.now() - baslangic
}));
} else {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
mesaj: 'Merhaba! Bu yanıtı veren worker:',
workerPid: process.pid,
workerId: cluster.worker.id,
zaman: new Date().toISOString()
}));
}
});
sunucu.listen(PORT, () => {
console.log(`Worker ${cluster.worker.id} (PID: ${process.pid}) port ${PORT} üzerinde dinliyor`);
});
// Master'a periyodik durum bilgisi gönder
setInterval(() => {
process.send({
tip: 'durum',
bellekKullanimi: process.memoryUsage().heapUsed,
pid: process.pid
});
}, 10000);
}
// ==============================
// Sıfır Kesinti ile Yeniden Başlatma
// ==============================
if (cluster.isMaster) {
function sifirKesintiGuncelleme() {
const workerIdleri = Object.keys(cluster.workers);
let indeks = 0;
function siradakiWorker() {
if (indeks >= workerIdleri.length) {
console.log('Tüm worker'lar güncellendi!');
return;
}
const eskiWorker = cluster.workers[workerIdleri[indeks]];
console.log(`Worker ${eskiWorker.id} kapatılıyor...`);
// Yeni worker başlat
const yeniWorker = cluster.fork();
yeniWorker.on('listening', () => {
console.log(`Yeni Worker ${yeniWorker.id} hazır.`);
// Eski worker'a kapanma sinyali gönder
eskiWorker.disconnect();
eskiWorker.on('disconnect', () => {
console.log(`Eski Worker ${eskiWorker.id} kapatıldı.`);
indeks++;
// 1 saniye bekle ve sonraki worker'a geç
setTimeout(siradakiWorker, 1000);
});
});
}
siradakiWorker();
}
// SIGUSR2 sinyali ile güncelleme tetikle
process.on('SIGUSR2', () => {
console.log('Güncelleme sinyali alındı!');
sifirKesintiGuncelleme();
});
}
Cluster modülü, Node.js uygulamalarınızı ölçeklendirmenin temel yoludur. Doğru kullanıldığında, aynı sunucudan çok daha yüksek performans alabilirsiniz. Ancak durum yönetimi, bellek kullanımı ve graceful shutdown konularına dikkat etmeniz şarttır. Production ortamında PM2 gibi araçlarla birlikte kullanmak en iyi pratiktir.
Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Kilitli
- Cevaplar
- 7
- Görüntüleme
- 2K
- Kilitli
- Cevaplar
- 1
- Görüntüleme
- 445
- Cevaplar
- 1
- Görüntüleme
- 522
- Cevaplar
- 0
- Görüntüleme
- 568
