Node.js Multithreading ve Worker Threads ile Yüksek Performans
Bu Rehberde Ne Öğreneceksiniz?
Bu rehber Node.js’te CPU yoğun işlemlerin neden sorun yarattığını açıklar.
Worker Threads ve worker pool kullanarak performansı nasıl artıracağınızı gösterir.
Teknik Özet
- Konu: Node.js Worker Threads
- Problem: CPU işlemleri event loop’u bloke eder
- Çözüm: worker_threads + Piscina
- Hedef: Tepkisel ve ölçeklenebilir API
Node.js Neden Multithreading’e İhtiyaç Duyar?
Node.js JavaScript kodunu tek thread üzerinde çalıştırır.
I/O işlemleri libuv sayesinde bloklama yapmaz.
Ancak hashleme, şifreleme ve resim işleme CPU’yu kilitler.
Bu durumda sunucu yeni isteklere cevap veremez.
Sorun: Ana Thread’i Bloklayan Örnek
import express from 'express';
import { createHash } from 'node:crypto';
const app = express();
app.get('/hizli', (req, res) => {
res.send('Bu istek hızlıdır.');
});
app.get('/agir-islem', (req, res) => {
let hash = '0';
for (let i = 0; i < 5_000_000; i++) {
hash = createHash('sha256').update(hash).digest('hex');
}
res.send('Ağır işlem tamamlandı.');
});
app.listen(3000);
- Bu kod çalışırken /agir-islem çağrısı tüm sunucuyu kilitler.
Çözüm: Worker Threads Kullanımı
- Ağır işlemi ayrı bir worker dosyasına taşıyoruz.
// worker.js
import { parentPort, workerData } from 'node:worker_threads';
import { createHash } from 'node:crypto';
let hash = workerData || '0';
for (let i = 0; i < 5_000_000; i++) {
hash = createHash('sha256').update(hash).digest('hex');
}
parentPort.postMessage(hash);
- Bu dosya yalnızca CPU işini yapar.
Ana Thread’den Worker Çalıştırma
import { Worker } from 'node:worker_threads';
function workerCalistir(veri) {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', {
workerData: veri
});
worker.on('message', resolve);
worker.on('error', reject);
});
}
- Bu fonksiyon ana thread’i bloke etmez.
Non-Blocking Endpoint
app.get('/non-blocking', async (req, res) => {
const sonuc = await workerCalistir('baslangic');
res.send(`Worker sonucu: ${sonuc}`);
});
- Bu rota çalışırken sunucu yanıt vermeye devam eder.
Neden Worker Pool Kullanılmalı?
-
Her istek için worker oluşturmak pahalıdır.
-
Worker pool, thread’leri yeniden kullanır.
-
Bu yaklaşım bellek ve gecikmeyi azaltır.
Piscina ile Worker Pool
import Piscina from 'piscina';
const pool = new Piscina({
filename: './worker.js',
minThreads: 2,
maxThreads: 4
});
export function havuzlaIslem(veri) {
return pool.run(veri);
}
- Piscina worker yaşam döngüsünü otomatik yönetir.
Ne Zaman Worker Threads Kullanılmamalı?
-
Veritabanı sorguları
-
HTTP istekleri
-
Dosya okuma işlemleri
-Bu işlemler async I/O ile daha verimlidir.
Prodüksiyon İçin Kritik İpuçları
-
Worker başına bellek sınırı koyun
-
Queue doluluğunu izleyin
-
Event loop gecikmesini ölçün
-
Docker CPU limitlerini worker sayısıyla eşleştirin
Sıkça Sorulan Sorular
1. Node.js gerçekten multithread mi? Evet. Worker Threads ile paralel JavaScript çalışır.
2. DB sorguları için worker kullanılır mı? Hayır. Bunlar I/O işlemleridir.
3. Kaç worker açmalıyım? Genelde CPU çekirdeği kadar.
4. Worker mı child process mi? Worker daha hafif ve hızlıdır.
Sonuç
Worker Threads, Node.js’i CPU yoğun işler için uygun hale getirir. Doğru havuzlama ile API’ler yüksek yük altında bile akıcı kalır.
Bu mimariyi Rabisu Bulut altyapısında güvenle kullanabilirsiniz.