Node.js İle Websocket Tabanlı Bildirim Servisi Nasıl Yapılır?

Node.js İle Websocket Tabanlı Bildirim Servisi Nasıl Yapılır?
Node.js İle Websocket Tabanlı Bildirim Servisi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce sisteminizde Node.js'in 20.x veya daha güncel bir sürümünün kurulu olduğundan emin olun. Geliştirme ortamınızda terminali açarak node -v komutu ile sürüm kontrolü yapabilirsiniz. Bu rehberde paket yöneticisi olarak npm kullanılacaktır.

Proje dizinini oluşturun ve gerekli bağımlılıkları yükleyin:

mkdir bildirim-servisi
cd bildirim-servisi
npm init -y
npm install express socket.io cors

Burada kullandığımız express web sunucusu çatısını, socket.io gerçek zamanlı iletişim kütüphanesini ve cors ise farklı kaynaklardan gelen istekleri yönetmek için gerekli olan güvenlik katmanını temsil eder.

Sunucu Tarafı Kurulumu ve Socket.io Entegrasyonu

Websocket bağlantısını başlatmak için öncelikle bir HTTP sunucusu oluşturmalı ve bu sunucuyu Socket.io ile sarmalamalıyız. Bu yapı, standart HTTP istekleri ile Websocket bağlantılarının aynı port üzerinden yönetilmesine olanak tanır.

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');

const app = express();
app.use(cors());

const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: "*", // Üretim ortamında burayı kendi domaininizle sınırlayın
    methods: ["GET", "POST"]
  }
});

io.on('connection', (socket) => {
  console.log('Yeni bir kullanıcı bağlandı: ', socket.id);

  socket.on('disconnect', () => {
    console.log('Kullanıcı ayrıldı');
  });
});

server.listen(3000, () => {
  console.log('Sunucu 3000 portunda çalışıyor.');
});

Bu kod bloğu, temel bir sunucu çatısı oluşturur. io.on('connection') fonksiyonu, her yeni bağlantı kurulduğunda tetiklenir ve istemciye özel bir socket nesnesi döndürür.

İstemci Tarafında Bildirim Alma

Sunucu tarafındaki bildirimleri tarayıcıda karşılamak için Socket.io istemci kütüphanesini kullanmalıyız. İstemci, sunucuya bağlandıktan sonra belirli olayları (events) dinlemeye başlar.

// İstemci tarafı (index.html veya main.js)
const socket = io("http://localhost:3000");

socket.on("bildirim", (data) => {
  console.log("Yeni bildirim geldi:", data.mesaj);
  alert("Yeni Bildirim: " + data.mesaj);
});

İstemci tarafında socket.on ile sunucudan gelecek olan "bildirim" olayını bekliyoruz. Veri geldiğinde ise kullanıcıya bir arayüz bildirimi gösteriyoruz.

Bildirim Gönderme Mekanizması

Bildirimleri tetiklemek için genellikle bir API endpoint'i kullanılır. Örneğin, bir veritabanı işlemi gerçekleştikten sonra sunucu üzerinden tüm bağlı kullanıcılara veya belirli bir kullanıcıya mesaj gönderebiliriz.

// Sunucu tarafında bildirim gönderme fonksiyonu
app.post('/bildirim-gonder', express.json(), (req, res) => {
  const { mesaj, kullaniciId } = req.body;
  
  // Tüm kullanıcılara gönder
  io.emit('bildirim', { mesaj });
  
  res.status(200).send({ status: 'Başarılı' });
});

Bu örnekte, bir POST isteği ile sunucuya bildirim tetiklenir. io.emit komutu, sunucuya bağlı olan tüm istemcilere veriyi anında yayınlar.

WebSocket ve HTTP Karşılaştırması

Bildirim sistemlerinde hangi yöntemin seçileceği, projenin ölçeğine ve ihtiyaçlarına bağlıdır. Aşağıdaki tablo, geleneksel HTTP ile WebSocket arasındaki temel farkları özetler.

Özellik HTTP (Polling) WebSocket
İletişim Yönü Tek yönlü (İstemci başlatır) Çift yönlü (Full-duplex)
Gecikme (Latency) Yüksek Çok Düşük
Sunucu Yükü Yüksek (Sürekli sorgu) Düşük (Sadece veri aktarımı)

Güvenlik ve Ölçeklendirme Uyarıları

Kritik Uyarı: WebSocket bağlantılarında kimlik doğrulama (authentication) ihmal edilmemelidir. Bağlantı kurulurken mutlaka JWT (JSON Web Token) gibi yöntemlerle kullanıcının kimliğini doğrulayın. Ayrıca, üretim ortamında origin: "*" ayarını mutlaka güvenli domain adreslerinizle kısıtlayın.

Üretim ortamında (production) bildirim servisi ölçeklenirken, tek bir sunucu yeterli olmayabilir. Redis kullanarak Socket.io'nun adapter yapısı üzerinden çoklu sunucu (multi-instance) desteği sağlayabilirsiniz.

Sıkça Sorulan Sorular

WebSocket bağlantısı koptuğunda ne olur?

Socket.io kütüphanesi otomatik olarak yeniden bağlanma (reconnection) mekanizmasına sahiptir. İstemci, sunucuya ulaşamadığında belirli aralıklarla tekrar deneme yapar.

Aynı anda binlerce kullanıcıya bildirim göndermek sunucuyu yorar mı?

Evet, ancak doğru bir mimari ile (örneğin Redis Pub/Sub kullanarak) yükü dağıtabilirsiniz. Node.js'in olay döngüsü (event loop) yapısı sayesinde binlerce eşzamanlı bağlantıyı yönetmek oldukça verimlidir.

Bildirimleri veritabanına kaydetmeli miyim?

Evet, WebSocket üzerinden gönderilen bildirimler geçicidir. Kullanıcı çevrimdışıysa bildirimi kaçıracaktır. Bu yüzden bildirimleri veritabanında saklayıp, kullanıcı giriş yaptığında "okunmamış bildirimler" olarak çekmek en iyi pratiktir.

Özel (Private) bildirimleri nasıl gönderirim?

Socket.io'da socket.join(userId) kullanarak kullanıcıları odalara (rooms) ayırabilir ve io.to(userId).emit(...) komutu ile sadece o kullanıcıya özel veri gönderebilirsiniz.

WebSocket yerine Server-Sent Events (SSE) kullanılır mı?

SSE, sadece sunucudan istemciye tek yönlü veri akışı için harikadır ve HTTP üzerinden çalıştığı için daha basittir. Ancak iki yönlü etkileşim gereken durumlarda WebSocket çok daha avantajlıdır.

WebSocket Bildirim Servislerinde Performans Optimizasyonu ve İzleme

WebSocket bağlantıları, HTTP isteklerine göre çok daha az kaynak tüketse de, binlerce eşzamanlı bağlantı yönetildiğinde sunucu tarafında bellek kullanımı ciddi bir sorun haline gelebilir. Performansı optimize etmek için sadece bağlantı sayısına değil, veri paketlerinin boyutuna ve sıklığına da odaklanmalısınız.

Mesaj Kuyruklama ve Redis Kullanımı

Büyük ölçekli uygulamalarda, bildirimleri doğrudan WebSocket üzerinden göndermek yerine bir mesaj kuyruğu (Message Broker) kullanmak, sunucunun yükünü dengeler. Özellikle Redis kullanarak "Pub/Sub" mekanizmasını devreye almak, birden fazla sunucu örneği (instance) arasında bildirim senkronizasyonu sağlar.

// Redis kullanarak bildirim yayını (Örnek mantık)
const redis = require('redis');
const publisher = redis.createClient();

function sendNotificationToUser(userId, message) {
    // Mesajı Redis kanalına yayınla
    publisher.publish('notifications', JSON.stringify({ userId, message }));
}

// Socket.io sunucusu Redis adaptörü ile bağlanır
const { createClient } = require('redis');
const { createAdapter } = require('@socket.io/redis-adapter');

const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

WebSocket Bağlantılarında Hata Ayıklama ve Test Stratejileri

WebSocket uygulamalarında hata ayıklamak, geleneksel REST API'lere göre daha karmaşıktır çünkü bağlantı durumu süreklidir. Bağlantı kopmaları, "handshake" hataları veya paket kayıpları genellikle istemci ve sunucu arasındaki ağ katmanında yaşanır.

İstemci Tarafı Bağlantı Durumu İzleme

Kullanıcı deneyimini iyileştirmek için istemci tarafında bağlantı durumlarını dinlemek ve buna göre UI (arayüz) güncellemesi yapmak kritik öneme sahiptir. Socket.io, bağlantı kopmalarını otomatik yönetse de, geliştirici olarak bu durumu kullanıcıya bildirmek profesyonel bir yaklaşımdır.

// İstemci tarafında bağlantı durumunu izleme
socket.on('connect', () => {
    console.log('Sunucuya bağlandı, bildirimler aktif.');
});

socket.on('disconnect', (reason) => {
    if (reason === 'io server disconnect') {
        // Bağlantı sunucu tarafından kesildi, manuel yeniden bağlan
        socket.connect();
    }
    console.warn('Bağlantı koptu:', reason);
});

socket.on('connect_error', (err) => {
    console.error('Bağlantı hatası oluştu:', err.message);
});

Yük Testi İçin Araçlar

Uygulamanızın canlıya çıkmadan önce ne kadar yükü kaldırabileceğini test etmek için Artillery veya Locust gibi araçları kullanabilirsiniz. Özellikle artillery-engine-socketio eklentisi, binlerce sanal kullanıcıyı simüle ederek WebSocket sunucunuzun performans darboğazlarını görmenizi sağlar.

İpucu: WebSocket sunucunuzu test ederken her zaman "ping/pong" mekanizmasının çalıştığından ve sunucunun boşta kalan (idle) bağlantıları belirli bir süre sonra temizlediğinden (timeout) emin olun.

Sonuç

Node.js ve Socket.io kullanarak bildirim servisi oluşturmak, modern web uygulamaları için en performanslı çözümlerden biridir. Bu rehberde, kurulumdan başlayarak sunucu ve istemci arasındaki iletişimi, güvenliği ve ölçeklendirme mantığını ele aldık. Bir sonraki adım olarak, bildirimleri veritabanı ile entegre etmeyi ve kullanıcıların çevrimdışı olduklarında kaçırdıkları bildirimleri yönetmeyi deneyebilirsiniz.

Yasal Uyarı: Bu rehberdeki kodlar eğitim amaçlıdır. Yazılım geliştirme süreçlerinde güvenlik yamalarını takip etmek, bağımlılıkları güncel tutmak ve sunucu güvenliğini (firewall, rate limiting) sağlamak geliştiricinin sorumluluğundadır. Bu makale herhangi bir hukuki veya ticari tavsiye niteliği taşımaz.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Zaman yönetimi ve üretkenlik ipuçları üzerine uzmanlaşmış bir içerik yazarıyım. Günlük yaşamı kolaylaştıran etkili yöntemleri okuyucularla paylaşarak hayat kalitesini artırmayı hedefliyorum.

Yorumlar (0)

Yorum Yaz