Node.js İle Socket.io Kullanarak Canlı Anlık Durum İzleme Ekranı Nasıl Yapılır?

Node.js İle Socket.io Kullanarak Canlı Anlık Durum İzleme Ekranı Nasıl Yapılır?
Node.js İle Socket.io Kullanarak Canlı Anlık Durum İzleme Ekranı Nasıl Yapılır?

Giriş

Modern web uygulamalarında kullanıcı deneyimini en üst düzeye çıkarmak için verilerin anlık olarak güncellenmesi kritik bir öneme sahiptir. Geleneksel HTTP istek-yanıt (request-response) modeli, sunucudaki dinamik değişiklikleri anında istemciye iletmekte yetersiz kalır. Bu rehberde, Node.js ile Socket.io kullanarak canlı anlık durum izleme ekranı nasıl yapılır sorusuna adım adım, çalışan kod örnekleriyle kapsamlı bir yanıt bulacaksınız. Bu eğitim sayesinde, sunucunuzun işlemci (CPU) ve bellek (RAM) kullanımını anlık olarak ölçüp, şık bir web arayüzünde gerçek zamanlı grafiklerle nasıl görselleştireceğinizi öğreneceksiniz.

WebSockets teknolojisi, istemci (tarayıcı) ile sunucu arasında çift yönlü (bidirectional) ve düşük gecikmeli bir iletişim kanalı açar. Socket.io ise bu teknolojiyi daha kararlı, tarayıcı uyumlu ve bağlantı kopmalarına karşı dayanıklı hale getiren en popüler Node.js kütüphanelerinden biridir. Bu makale, orta seviye JavaScript bilgisine sahip, Node.js ekosisteminde gerçek zamanlı (real-time) uygulamalar geliştirmek isteyen tüm yazılımcılar ve sistem yöneticileri için hazırlanmıştır.

Eğitim boyunca oluşturacağımız proje, sistem kaynaklarını izleyen (system monitoring) bir panel olacaktır. Sunucu tarafında sistem bilgilerini okuyup, Socket.io aracılığıyla ön yüze aktaracağız. Ön yüzde ise bu verileri modern bir grafik kütüphanesi yardımıyla anlık olarak güncelleyeceğiz. Hazırsanız, gerekli ortam kurulumları ile projemize başlayalım.

Gereksinimler ve Ön Hazırlık

Uygulamamızı geliştirmeye başlamadan önce bilgisayarınızda gerekli çalışma ortamının kurulu olduğundan emin olmalısınız. 2026 yılı standartlarına uygun olarak, modern ES modüllerini (ES Modules) ve güncel Node.js özelliklerini kullanacağız.

  • Node.js: Bilgisayarınızda Node.js v20 veya üzeri bir sürümün kurulu olması önerilir. Sürümünüzü kontrol etmek için terminale node -v yazabilirsiniz.
  • npm (Node Package Manager): Node.js ile birlikte gelen paket yöneticisi.
  • Kod Editörü: Visual Studio Code veya tercih ettiğiniz herhangi bir modern kod editörü.
  • Temel Terminal Bilgisi: Klasör oluşturma, paket yükleme ve sunucu başlatma komutlarını çalıştırabilmek.

Gereksinimleri karşıladıktan sonra, projemiz için boş bir dizin oluşturup terminal üzerinden bu dizine geçiş yapalım. Ardından projemizi initialize (başlatma) ederek bağımlılıklarımızı kurmaya hazır hale getirelim.

Adım 1: Proje Kurulumu ve Bağımlılıkların Yüklenmesi

İlk adımda, projemizin temel yapı taşını oluşturacak olan package.json dosyasını oluşturacağız. Bu projede modern JavaScript sözdizimini (import/export) kullanabilmek için projemizi "module" tipinde tanımlayacağız. Terminalinizi açın ve aşağıdaki komutları sırasıyla çalıştırın:

mkdir nodejs-socketio-monitor
cd nodejs-socketio-monitor
npm init -y

Bu komutlar, projemiz için yeni bir klasör oluşturur ve varsayılan ayarlarla bir Node.js projesi başlatır. Şimdi projemizde kullanacağımız paketleri yüklememiz gerekiyor. Bize gereken paketler şunlardır:

  • express: Minimalist web sunucusu oluşturmak için.
  • socket.io: Gerçek zamanlı çift yönlü iletişim sağlamak için.
  • systeminformation: Sunucunun CPU, RAM ve diğer sistem bilgilerini anlık olarak okumak için.

Aşağıdaki komutu terminalde çalıştırarak bu üç paketi projenize dahil edin:

npm install express socket.io systeminformation

Yükleme tamamlandıktan sonra, projenin kök dizininde bulunan package.json dosyasını açın ve modern ES modüllerini kullanabilmek için "type": "module" satırını ekleyin. Dosyanızın son hali aşağıdaki örnek kod gibi görünmelidir:

{
  "name": "nodejs-socketio-monitor",
  "version": "1.0.0",
  "type": "module",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.21.0",
    "socket.io": "^4.8.0",
    "systeminformation": "^5.23.0"
  }
}

Yukarıdaki yapılandırma sayesinde, Node.js üzerinde require yerine modern import sözdizimini kullanabileceğiz. Ayrıca npm start komutu ile sunucumuzu kolayca başlatabileceğiz.

Adım 2: Node.js Sunucusunun Oluşturulması ve Socket.io Entegrasyonu

Proje dizininde server.js adında bir dosya oluşturun. Bu dosya, Express web sunucusunu barındıracak, HTTP isteklerini karşılayacak ve Socket.io sunucusunu başlatacaktır. Socket.io, mevcut bir HTTP sunucusu üzerine inşa edilir; bu nedenle Express sunucumuzu doğrudan Node.js'in yerleşik http modülü ile sarmalayacağız.

Aşağıdaki örnek kod, Express ve Socket.io entegrasyonunun en temel ve güvenli kurulumunu göstermektedir. Kodun satır satır açıklaması bloktan sonra yer almaktadır:

import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = express();
const httpServer = createServer(app);

// Socket.io yapılandırması ve CORS ayarları
const io = new Server(httpServer, {
  cors: {
    origin: "*", // Geliştirme ortamı için tüm kökenlere izin verilir
    methods: ["GET", "POST"]
  }
});

// Statik dosyaların sunulması
app.use(express.static(path.join(__dirname, 'public')));

// İstemci bağlantı yönetimi
io.on('connection', (socket) => {
  console.log(`Yeni bir istemci bağlandı. ID: ${socket.id}`);

  socket.on('disconnect', (reason) => {
    console.log(`İstemci ayrıldı. ID: ${socket.id}, Neden: ${reason}`);
  });
});

const PORT = process.env.PORT || 3000;
httpServer.listen(PORT, () => {
  console.log(`Sunucu http://localhost:${PORT} adresinde çalışıyor.`);
});

Bu kod bloğunda neler yaptık? İlk olarak, modern ES modüllerinde __dirname değişkeni doğrudan bulunmadığı için url ve path modüllerini kullanarak bu yolu manuel olarak tanımladık. Ardından, bir Express uygulaması oluşturup bunu Node.js createServer fonksiyonuna parametre olarak geçtik. new Server(httpServer) satırı ile Socket.io'yu bu HTTP sunucusuna bağladık.

io.on('connection', ...) bloğu, sunucuya yeni bir tarayıcı veya istemci bağlandığında tetiklenir. Her istemciye benzersiz bir socket.id atanır. İstemci sekmesini kapattığında veya bağlantısı koptuğunda ise disconnect olayı (event) devreye girer.

Adım 3: Sistem Verilerini Toplama ve Socket.io ile Yayınlama

Canlı durum izleme ekranımızın kalbini, sunucudan toplanan anlık metrikler oluşturur. Bu adımda, systeminformation kütüphanesini kullanarak CPU yükünü ve RAM kullanımını periyodik olarak ölçeceğiz. Elde ettiğimiz bu verileri, bağlı olan tüm istemcilere Socket.io'nun emit (yayınlama) yöntemiyle göndereceğiz.

Aşağıdaki kod bloğunda, her 2 saniyede bir sistem verilerini toplayıp istemcilere gönderen fonksiyonu server.js dosyamıza entegre ediyoruz. Mevcut server.js dosyanızı aşağıdaki şekilde güncelleyin:

import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';
import path from 'path';
import { fileURLToPath } from 'url';
import si from 'systeminformation';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
  cors: { origin: "*" }
});

app.use(express.static(path.join(__dirname, 'public')));

// Sistem verilerini toplayıp yayınlayan fonksiyon
async function sendSystemMetrics() {
  try {
    // CPU yükü ve Bellek bilgilerini paralel olarak çekiyoruz
    const [cpuData, memData] = await Promise.all([
      si.currentLoad(),
      si.mem()
    ]);

    const metrics = {
      cpu: {
        usage: Math.round(cpuData.currentLoad),
        cores: cpuData.cpus.map(core => Math.round(core.load))
      },
      ram: {
        total: (memData.total / (1024 * 1024 * 1024)).toFixed(2), // GB cinsinden
        used: (memData.used / (1024 * 1024 * 1024)).toFixed(2),
        percentage: Math.round((memData.used / memData.total) * 100)
      },
      timestamp: new Date().toLocaleTimeString('tr-TR')
    };

    // Tüm bağlı istemcilere 'metrics_update' kanalı üzerinden veriyi gönder
    io.emit('metrics_update', metrics);
  } catch (error) {
    console.error("Sistem verileri alınırken hata oluştu:", error);
  }
}

// Her 2 saniyede bir verileri güncelle ve gönder
let metricsInterval;

io.on('connection', (socket) => {
  console.log(`İstemci bağlandı: ${socket.id}`);

  // İlk bağlantıda hemen veri gönder
  sendSystemMetrics();

  // Eğer ilk istemci bağlandıysa ve interval çalışmıyorsa başlat
  if (!metricsInterval && io.engine.clientsCount > 0) {
    metricsInterval = setInterval(sendSystemMetrics, 2000);
    console.log("Veri toplama döngüsü başlatıldı.");
  }

  socket.on('disconnect', () => {
    console.log(`İstemci ayrıldı: ${socket.id}`);
    // Bağlı istemci kalmadıysa interval'i temizle (kaynak tasarrufu)
    if (io.engine.clientsCount === 0) {
      clearInterval(metricsInterval);
      metricsInterval = null;
      console.log("Aktif istemci kalmadı. Veri toplama döngüsü durduruldu.");
    }
  });
});

const PORT = process.env.PORT || 3000;
httpServer.listen(PORT, () => {
  console.log(`Sunucu http://localhost:${PORT} adresinde aktif.`);
});

Bu güncellenmiş kodda, Promise.all kullanarak CPU ve RAM bilgilerini asenkron olarak aynı anda çektik. Bu işlem, sunucu üzerindeki I/O (girdi/çıktı) yükünü minimize eder. io.emit('metrics_update', metrics) ifadesi, o anda sunucuya bağlı olan tüm tarayıcılara tek bir hamlede veriyi yayınlar (broadcast).

Önemli Performans Uyarısı: Sunucuda aktif olarak bağlı hiçbir kullanıcı yoksa, arka planda sürekli sistem verisi toplamak gereksiz CPU tüketimine yol açar. Bu yüzden yukarıdaki kodda, io.engine.clientsCount değerini kontrol ederek yalnızca en az bir istemci bağlı olduğunda setInterval döngüsünü çalıştırdık. Son istemci ayrıldığında döngüyü durdurarak kaynak tasarrufu sağladık.

Adım 4: Ön Yüz (Frontend) Tasarımı ve Socket.io İstemci Kurulumu

Şimdi istemci tarafını oluşturma zamanı. Projenizin kök dizininde public adında bir klasör oluşturun. Bu klasörün içerisine index.html dosyasını ekleyin. Ön yüzde modern ve temiz bir görünüm elde etmek için Tailwind CSS (CDN üzerinden) ve grafik çizimi için popüler bir kütüphane olan Chart.js kullanacağız.

Aşağıdaki HTML kodunu public/index.html dosyasına yapıştırın:




  
  
  Canlı Sistem Durum İzleme Paneli
  
  
  
  
  
  



  

Canlı Sistem İzleme Ekranı

Node.js ve Socket.io ile anlık sunucu metrikleri

Bağlanıyor...

CPU Kullanımı

0%

RAM Kullanımı

0%

Kullanılan: 0 GB / Toplam: 0 GB

Zaman Serisi Analizi

&

Performans Optimizasyonu ve Veri Akış Yönetimi

Canlı sistem izleme panellerinde, sunucudan istemciye saniyede onlarca kez veri gönderilmesi ağ trafiğini ve tarayıcı performansını olumsuz etkileyebilir. Bu durumu engellemek için "throttle" (kısıtlama) ve "debounce" tekniklerini kullanmak kritik öneme sahiptir.

Sunucu tarafında, verileri her milisaniyede bir göndermek yerine, belirli bir aralıkta (örneğin 1 saniyede bir) yayınlamak sistem kaynaklarını korur. Aşağıdaki kod bloğu, verinin yayınlanma sıklığını nasıl optimize edebileceğinizi gösterir:

// Sunucu tarafında yayınlama aralığını kontrol etme
let lastEmitTime = 0;
const emitInterval = 1000; // 1 saniye

setInterval(async () => {
  const now = Date.now();
  if (now - lastEmitTime >= emitInterval) {
    const stats = await getSystemStats();
    io.emit('system-stats', stats);
    lastEmitTime = now;
  }
}, 500);

İstemci tarafında ise, Chart.js grafiklerinin sürekli güncellenmesi DOM üzerinde yoğun bir yük oluşturur. Grafik verilerini güncellerken chart.update('none') metodunu kullanarak animasyonları devre dışı bırakmak veya veri dizisinin uzunluğunu sınırlamak (örneğin sadece son 50 veri noktasını tutmak) tarayıcının donmasını engeller.

Üretim Ortamında (Production) Hata Ayıklama ve Deployment

Geliştirme aşamasında çalışan sistemin canlı ortama taşınması sırasında Socket.io bağlantılarının kopması veya güvenlik duvarı (firewall) engelleri ile karşılaşabilirsiniz. Üretim ortamında dikkat etmeniz gereken temel noktalar şunlardır:

  • Güvenlik: Socket.io bağlantılarını sadece güvenilir domainlerden gelen isteklere izin verecek şekilde (CORS politikası) yapılandırın.
  • Nginx Yapılandırması: Nginx kullanıyorsanız, WebSocket bağlantılarını desteklemesi için Upgrade ve Connection header'larını doğru şekilde yönlendirdiğinizden emin olun.
  • Loglama: Hataları izlemek için pm2 gibi süreç yöneticileri kullanarak uygulamanın çökmesi durumunda otomatik yeniden başlatılmasını sağlayın.

Aşağıdaki Nginx yapılandırması, WebSocket trafiğinin doğru şekilde iletilmesi için gereklidir:

location /socket.io/ {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}

Uygulamanızı canlıya alırken, NODE_ENV=production değişkenini ayarlamayı unutmayın. Bu, Socket.io'nun hata ayıklama modundan çıkıp daha performanslı bir çalışma moduna geçmesini sağlar.

Bu yazıya tepkinizi paylaşın:
Mert Çelik

Kendin yap (DIY) projeleri ve ev içi bakım rehberleri üzerine içerik geliştiriyorum. Detaylı ve anlaşılır anlatım diliyle karmaşık işleri keyifli hale getiriyorum.

Yorumlar (0)

Yorum Yaz