Ana içeriğe geç

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 &#123; createHash &#125; 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 &#123; Worker &#125; 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: $&#123;sonuc&#125;`);
});
  • 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ı?

  1. Veritabanı sorguları

  2. HTTP istekleri

  3. Dosya okuma işlemleri

-Bu işlemler async I/O ile daha verimlidir.


Prodüksiyon İçin Kritik İpuçları

  1. Worker başına bellek sınırı koyun

  2. Queue doluluğunu izleyin

  3. Event loop gecikmesini ölçün

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