Node.js ile Socket.io Gerçek Zamanlı Uygulamalar

Node.js ve Socket.io ile Gerçek Zamanlı Uygulama Geliştirme Rehberi

Modern web uygulamalarında kullanıcı deneyimini en üst seviyeye çıkarmak için gerçek zamanlı (real-time) veri iletişimi kritik bir rol oynar. Bu makalede, Node.js ve Socket.io kütüphanesini kullanarak düşük gecikmeli, çift yönlü iletişim sistemlerinin nasıl kurulacağını, SQL veritabanı entegrasyonunu ve üretim ortamı için en iyi uygulama (best practices) yöntemlerini derinlemesine inceleyeceğiz.

Bilgi: Socket.io, sadece bir WebSocket sarmalayıcısı değildir; bağlantı kopmalarında otomatik yeniden bağlanma, oda (room) yönetimi ve WebSocket desteklemeyen tarayıcılar için HTTP long-polling desteği sunan gelişmiş bir kütüphanedir.

Socket.io ve Geleneksel HTTP Arasındaki Farklar

Geleneksel HTTP protokolü "request-response" (istek-yanıt) modeline dayanır. İstemci bir istek gönderir ve sunucu yanıt verir. Ancak canlı sohbet, borsa takibi veya çok oyunculu oyunlar gibi uygulamalarda sunucunun istemciye veri itmesi (push) gerekir.

Özellik HTTP Protokolü Socket.io (WebSocket)
İletişim Tipi Tek Yönlü (Unidirectional) Çift Yönlü (Bidirectional)
Gecikme (Latency) Yüksek (Her istekte header gönderilir) Düşük (Sürekli açık bağlantı)
Veri Transferi İstemci tetikler Sunucu veya İstemci tetikleyebilir

Node.js ve Socket.io Kurulumu

Projenize başlamak için Node.js ortamınızın kurulu olduğundan emin olun. İlk adım olarak gerekli bağımlılıkları yükleyelim:

npm install express socket.io
npm install mysql2 // SQL entegrasyonu için

Temel Sunucu Yapılandırması

Aşağıdaki örnek, temel bir Express sunucusu üzerinde Socket.io'nun nasıl ayağa kaldırılacağını göstermektedir:

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

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
    cors: {
        origin: "*", // Güvenlik için üretimde spesifik domain yazılmalıdır
    }
});

io.on('connection', (socket) => {
    console.log('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.');
});

SQL Veritabanı ile Gerçek Zamanlı Veri Senkronizasyonu

Gerçek dünya senaryolarında, genellikle bir SQL veritabanına veri yazıldığında tüm bağlı istemcilerin güncellenmesi istenir. Örneğin, bir sipariş takip sisteminde sipariş durumu değiştiğinde kullanıcıya anlık bildirim gitmelidir.

Örnek: SQL'den Veri Çekme ve Yayınlama (Emit)

Veritabanında bir değişiklik olduğunda bunu dinleyen ve bağlı tüm istemcilere yayınlayan bir yapı kuralım:

const mysql = require('mysql2');

const db = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'app_db'
});

// Yeni mesaj geldiğinde veritabanına kaydet ve herkese yayınla
socket.on('new_message', (data) => {
    const query = 'INSERT INTO messages (user_id, content) VALUES (?, ?)';
    db.query(query, [data.userId, data.content], (err, result) => {
        if (!err) {
            // Tüm istemcilere (gönderen dahil) veriyi gönder
            io.emit('receive_message', {
                id: result.insertId,
                content: data.content,
                userId: data.userId
            });
        }
    });
});

Socket.io Olay Yönetimi (Broadcasting ve Rooms)

Socket.io'da veriyi kimin alacağını kontrol etmek için farklı yöntemler bulunur:

  • io.emit(): Bağlı olan herkese gönderir.
  • socket.broadcast.emit(): Gönderen kişi hariç herkese gönderir.
  • socket.to(room).emit(): Sadece belirli bir "odadaki" kullanıcılara gönderir.

Odalar (Rooms) Kullanımı

Özellikle özel mesajlaşma veya belirli bir gruba bildirim gönderme senaryolarında kullanılır:

// Kullanıcıyı belirli bir odaya dahil etme
socket.on('join_room', (roomName) => {
    socket.join(roomName);
    console.log(`${socket.id} adlı kullanıcı ${roomName} odasına katıldı.`);
});

// Sadece o odadakilere mesaj gönderme
socket.to('private_room').emit('private_notice', 'Bu sadece bu odaya özeldir.');

Güvenlik ve Performans İçin En İyi Uygulamalar (Best Practices)

Önemli: Socket.io bağlantıları stateful (durumsal) olduğu için binlerce anlık bağlantıda bellek yönetimi kritikleşir.

1. Kimlik Doğrulama (Authentication)

Bağlantı kurulmadan önce JWT (JSON Web Token) kullanarak kimlik doğrulaması yapmak güvenliğin ilk adımıdır:

io.use((socket, next) => {
    const token = socket.handshake.auth.token;
    if (isValid(token)) {
        next();
    } else {
        next(new Error("Yetkisiz erişim!"));
    }
});

2. Ölçeklenebilirlik (Scalability)

Uygulamanız birden fazla sunucuda (Node.js cluster) çalışıyorsa, sunucular arası haberleşme için Redis Adapter kullanmalısınız. Aksi takdirde, Sunucu A'ya bağlı bir kullanıcı, Sunucu B'ye bağlı bir kullanıcıya mesaj gönderemez.

3. Hata Yönetimi

İstemci tarafında `connect_error` ve `reconnect_attempt` olaylarını dinleyerek kullanıcıya bağlantı durumu hakkında bilgi vermek, kullanıcı deneyimini iyileştirir.

Sonuç

Node.js ve Socket.io ikilisi, SQL veritabanlarıyla entegre edildiğinde son derece güçlü ve ölçeklenebilir gerçek zamanlı sistemler oluşturmanıza olanak tanır. Olay tabanlı mimariyi doğru kurgulamak, odaları (rooms) verimli kullanmak ve güvenlik katmanlarını (middleware) ihmal etmemek, profesyonel bir uygulamanın temel taşlarıdır. Daha fazla bilgi için resmi Socket.io dökümantasyonunu inceleyebilirsiniz.