Node JS Uygulamamızı Ölçeklendirme

Ali KARABAY
3 min readSep 30, 2022

--

Mevcut uygulama kodumuzu değiştirmeye gerek kalmadan PM2 ve cluster’ı kullanarak Node uygulamalarımızı artan trafik yükleri için nasıl kolayca ölçekleyebileceğimize bir göz atalım.

PM2

PM2 , Node.js uygulamaları’nı production ortamında ölçeklendirmeyi kolaylaştıran yerleşik bir load balancer’a sahiptir.

Aşağıdaki komutu kullanarak sisteminize yükleyebilirsiniz

npm i -g pm2

Node JS

Node.js, V8 JavaScript motorunun üzerine kurulduğundan, bir thread kullanır. Bu nedenle uygulamanız tek bir thread üzerinde çalışır ve bu nedenle mevcut sistem kaynaklarını tam olarak kullanmaz.

Event Loop, orta düzeyde trafik yüklerinde çoğu kullanım durumu için yeterince verimli olduğundan, Event tabanlı I/O callback’leri için bu ciddi bir sorun olmayabilir. Sorun artan trafik sonucunda servislerimizin geç cevap verme durumunda ortaya çıkar

Node.js Cluster Modülü:

Yukarıda tek bir thread’de çıkacak sorun için Node.js’deki cluster modülü bu sorunu çözülebilir.

Aşağıdaki gibi basit bir Node server’ımız olduğunu varsayalım:

//server.js

const http = require("http");

http.createServer((req, res) => {
res.writeHead(200);
res.end("server endpoint");
}).listen(8080);

Şimdi doğrudan Node.js cluster modülünü kullanalım ve mevcut kodu aşağıdaki gibi değiştirerek bir cluster mantığı içine koymanız gerekiyor:

//server.jsconst http = require("http");
const os = require("os");
const cluster = require("cluster");
const cpuCores = os.cpus().length;if (cluster.isMaster) {
let instance = 0;
while (instance < cpuCores) {
cluster.fork();
++instance;
}
} else {
console.log(`Child-process ${process.pid} started`);
http.createServer((req, res) => {
res.writeHead(200);
res.end("server endpoint");
}).listen(8080);
}

Bunu sekiz çekirdekli bir makinede çalıştırdığında, 8080 portunda aşağıdaki gibi paylaşan ayrı worker’larda (child processes) uygulamanın 8 tane kopyasını aldı:

çalışan child processes’ler

Cluster Modülünü Kullanmanın Dezavantajları

Yukarıda ele aldığımız örnek oldukça basit, ancak bunda bile, child processes’ler beklenmedik bir şekilde sonlandırılmasını ele alma durumunu gözden kaçırdık.

Mevcut uygulamamızla, bir child processes (worker) sonlandırıldığında, yerini alacak yeni bir process oluşturulmayacaktır. Tabii ki, exitolayı cluster örneğinde dinleyerek ve çıkışta yeni worker’ları oluşturabiliriz ancak buradaki nokta, yukarıdaki gibi basit bir uygulama için bile, oldukça hızlı bir şekilde karmaşıklaşıyor.

İkinci fakat en belirgin dezavantaj, bu çalışmayı elde etmek için mevcut kodumuzu değiştirmemiz gerektiğidir.

Ya mevcut kodumuza dokunmak zorunda kalmadan tüm bu cluster mantığı, yeniden bir process oluşturma, load balancer vb. ile başa çıkmanın bir yolu olsaydı? işte, PM2 tam burada devreye giriyor.

PM2

PM2 dahili olarak Node.js cluster modülünü kullanır, ancak uç durumlar da dahil olmak üzere her şey bizim için işlenir ve bunu çalıştırmak için mevcut kodumuza dokunmamız bile gerekmez.

Yani, hala kodumuzu aşağıdaki gibi alabiliriz:

//server.jsconst http = require("http");http.createServer((req, res) => {
res.writeHead(200);
res.end("server endpoint");
}).listen(8080);

Ama önce bir yapılandırma dosyası oluşturuyoruz:

pm2 ecosystem

Yukarıdaki komut ecosystem.config.js, adında bir dosya oluşturur. Oluşturulan dosyayı aşağıdaki gibi değiştirmemiz gerekecek:

//ecosystem.config.jsmodule.exports = {
apps: [
{
name: "demo-app",
script: "server.js",
instances: 0,
exec_mode: "cluster",
watch: ".",
},
],
deploy: {
production: {
user: "YOUR_SSH_USERNAME_HERE",
host: "YOUR_SSH_HOST_ADDRESS",
ref: "YOUR_GIT_BRANCH_REF (eg: origin/master)",
repo: "GIT_REPOSITORY",
path: "YOUR_DESTINATION_PATH_ON_SERVER",
"pre-deploy-local": "",
"post-deploy":"npm install && pm2 reload ecosystem.config.js --env production",
"pre-setup": "",
},
},
};

Burada dikkat edilmesi gereken üç alan vardır:

  1. exec_mode: "cluster"PM2'ye kodu yürütmek için Node.js cluster modülünü kullanmasını söyler.
  2. instances:0bu 0 olarak ayarlandığında, PM2 otomatik olarak mevcut çekirdek sayısına eşit sayıda child processes oluşturacaktır. Exit olma durumlarında yeniden oluşturulacaktır.
  3. "post-deploy": "npm install && pm2 reload ecosystem.config.js -env production"Burada dikkat edilmesi gereken en önemli nokta , örneklerin birbiri ardına durdurulduğu ve en son değişikliklerle başlatıldığı sürekli bir deploymentpm2 reload yaklaşımını benimseyerek hiçbir şekilde uygulama down etmeden bir deployment yapacaktır .

Şimdi PM2 kullanarak uygulamamızı başlatalım:

pm2 start ecosystem.config.js

Yukarıdaki adımlarla, şimdi basit demo uygulamamızı 8x, sistemin mevcut çekirdeklerini kullanarak ve hatta mevcut koda dokunmadan normal yükünün üstesinden gelecek şekilde ölçeklendirdik:

PM2 Clusters

Gerçekten bir yapılandırma dosyasına ihtiyacınız yoksa ve yalnızca tek bir uygulama çalıştırıyorsanız, bunun yerine aşağıdaki PM2 komutunu da kullanabilirsiniz:

pm2 start server.js -i 0

Böylece, artan yüklerin üstesinden gelmek için Node.js uygulamalarını nasıl kolayca ölçekleyebileceğimizi gördük. PM2 bundan çok daha fazlasını yapabilir ve ilgilenenler dökümantasyonunu inceleyebilir.

30 Eylül 2022 tarihinde https://www.karabayyazilim.com adresinde yayınlanmıştır.

--

--