Php İle Websocket Kullanarak Gerçek Zamanlı Bildirim Sistemi Nasıl Yapılır?

Php İle Websocket Kullanarak Gerçek Zamanlı Bildirim Sistemi Nasıl Yapılır?
Php İle Websocket Kullanarak Gerçek Zamanlı Bildirim Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Websocket projeleri için sunucu tarafında uzun süre çalışan (daemon) süreçlere ihtiyaç duyarız. Bu nedenle, paylaşımlı hosting yerine SSH erişimi olan bir VPS (Sanal Özel Sunucu) kullanmanız önerilir. Projemiz için gerekli olan temel araçlar şunlardır:

  • PHP 8.2 veya üzeri bir sürüm.
  • Composer (PHP paket yöneticisi).
  • Ratchet (PHP için Websocket kütüphanesi).
  • Node.js ve NPM (İstemci tarafı testleri için opsiyonel).

Kurulumu tamamlamak için terminalinizde proje dizinine giderek şu komutu çalıştırın:

composer require cboden/ratchet

Bu komut, projenize Ratchet kütüphanesini dahil edecektir. Ratchet, PHP üzerinde asenkron (eşzamansız) işlemler yapmanıza olanak tanıyan ReactPHP tabanlı bir kütüphanedir.

Websocket Sunucusunun Kodlanması

Websocket sunucusu, istemcilerden gelen bağlantıları kabul eden ve mesajları yönlendiren bir merkezdir. Ratchet kütüphanesini kullanarak MessageComponentInterface arayüzünü (interface) uygulayan bir sınıf oluşturacağız.


use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class BildirimSunucusu implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "Yeni bağlantı: ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            $client->send($msg);
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }
}

Yukarıdaki kod, bağlanan her istemciyi $clients nesnesinde tutar. Bir mesaj geldiğinde, bu mesajı tüm bağlı istemcilere yayınlar (broadcast). Bu, bildirim sisteminin temelini oluşturur.

Sunucunun Çalıştırılması

Oluşturduğumuz sınıfı bir port üzerinden dinlemeye başlamamız gerekir. Bunun için server.php adında bir dosya oluşturup aşağıdaki yapılandırmayı ekleyin.


use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;

require dirname(__DIR__) . '/vendor/autoload.php';

$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new BildirimSunucusu()
        )
    ),
    8080
);

$server->run();

Bu kodu terminalde php server.php komutuyla çalıştırdığınızda, sunucunuz 8080 portunda WebSocket isteklerini beklemeye başlayacaktır. Güvenlik duvarınızda bu portun açık olduğundan emin olun.

İstemci Tarafı: JavaScript İle Bağlantı Kurma

İstemci tarafında, tarayıcının yerel WebSocket API'sini kullanacağız. Bu API, sunucuya bağlanmak ve gelen verileri dinlemek için oldukça basittir.


const conn = new WebSocket('ws://sunucu-adresiniz:8080');

conn.onopen = function(e) {
    console.log("Sunucuya bağlanıldı!");
};

conn.onmessage = function(e) {
    const bildirim = JSON.parse(e.data);
    alert("Yeni Bildirim: " + bildirim.mesaj);
};

Bu JavaScript kodu, sayfa yüklendiğinde sunucuya bağlanır. Sunucudan bir mesaj geldiğinde ise onmessage olayı tetiklenir ve kullanıcıya bir bildirim gösterilir.

Bildirim Sistemi Karşılaştırma Tablosu

Yöntem Gerçek Zamanlılık Sunucu Yükü Zorluk Derecesi
AJAX Polling (Düzenli İstek) Düşük Yüksek Kolay
Websocket Çok Yüksek Düşük Orta
Server-Sent Events (SSE) Yüksek Düşük Kolay

Güvenlik ve Performans İpuçları

Kritik Uyarı: WebSocket bağlantılarında XSS (Cross-Site Scripting) saldırılarına karşı gelen verileri mutlaka temizleyin. Ayrıca, üretim ortamında (production) mutlaka WSS (WebSocket Secure - SSL sertifikalı) protokolünü kullanın. Aksi takdirde verileriniz ağ üzerinde şifresiz olarak taşınacaktır.

WebSocket sunucunuzun çökmemesi için süreci arka planda yöneten Supervisor gibi araçlar kullanın. Supervisor, sunucu betiğiniz kapandığında onu otomatik olarak yeniden başlatır.

Sıkça Sorulan Sorular

WebSocket bağlantım sürekli kopuyor, ne yapmalıyım?

WebSocket bağlantıları uzun süre boşta kaldığında sunucu veya proxy (Nginx/Apache) tarafından kapatılabilir. Bağlantıyı canlı tutmak için "ping/pong" mekanizması kullanabilir veya sunucu tarafında zaman aşımı ayarlarını kontrol edebilirsiniz.

Birden fazla kullanıcıya özel bildirim nasıl gönderirim?

Kullanıcıları $clients nesnesinde tutarken, her bağlantıya bir kullanıcı ID'si atayın. Mesaj gönderirken hedef ID'yi kontrol ederek sadece ilgili bağlantıya veri gönderin.

Nginx ile WebSocket nasıl kullanılır?

Nginx kullanıyorsanız, location bloğunda proxy_set_header Upgrade $http_upgrade; ve proxy_set_header Connection "Upgrade"; ayarlarını yaparak WebSocket trafiğini PHP sunucunuza yönlendirmeniz gerekir.

Veritabanı ile nasıl entegre ederim?

WebSocket sunucunuz içinde bir veritabanı bağlantısı (PDO) oluşturarak, gelen mesajları veritabanına kaydedebilir ve ardından diğer istemcilere yayınlayabilirsiniz.

WebSocket yerine neden SSE kullanmayayım?

SSE sadece sunucudan istemciye tek yönlü veri akışı sağlar. Eğer uygulamanızda istemciden sunucuya da anlık veri gönderimi (örneğin anlık mesajlaşma) gerekiyorsa, WebSocket çok daha esnek bir çözümdür.

WebSocket Sunucularında Hata Ayıklama ve Loglama Stratejileri

WebSocket uygulamaları, geleneksel HTTP istek-cevap döngüsünden farklı çalıştığı için hata ayıklama süreçleri daha karmaşık olabilir. Sunucu tarafında bir hata oluştuğunda, istemci bağlantısı sessizce kopabilir veya veriler iletilemeyebilir. Bu durumları minimize etmek için profesyonel bir loglama mekanizması kurmanız şarttır.

Ratchet üzerinde çalışırken, onMessage ve onError metotlarını genişleterek her adımı kayıt altına almalısınız. Aşağıdaki örnek, hataları bir dosyaya yazarak izlemenizi sağlar:

public function onError(ConnectionInterface $conn, \Exception $e) {
    $logMessage = sprintf(
        "[%s] Hata: %s - Dosya: %s:%d\n",
        date('Y-m-d H:i:s'),
        $e->getMessage(),
        $e->getFile(),
        $e->getLine()
    );
    file_put_contents('websocket_errors.log', $logMessage, FILE_APPEND);
    $conn->close();
}

Ayrıca, tarayıcı konsolunda ws.onerror olayını dinleyerek istemci tarafındaki bağlantı hatalarını anlık olarak yakalayabilir ve kullanıcıya "Bağlantı koptu, tekrar deneniyor..." gibi bilgilendirmeler yapabilirsiniz.

Üretim Ortamında (Production) Süreç Yönetimi: Supervisor

WebSocket sunucunuzu terminalde php bin/server.php komutuyla çalıştırmak, sunucu kapandığında veya hata aldığında uygulamanızın durmasına neden olur. Üretim ortamında sunucunun sürekli ayakta kalmasını sağlamak için Supervisor kullanmalısınız.

Supervisor, bir süreç (process) yöneticisidir ve belirlediğiniz komutun çökmesi durumunda onu otomatik olarak yeniden başlatır. /etc/supervisor/conf.d/websocket.conf dosyasına şu yapılandırmayı ekleyerek sisteminizi kararlı hale getirebilirsiniz:

[program:websocket-server]
command=php /var/www/html/bin/server.php
user=www-data
autostart=true
autorestart=true
stderr_logfile=/var/log/websocket.err.log
stdout_logfile=/var/log/websocket.out.log

Bu yapılandırma ile sunucunuz, sistem yeniden başlatıldığında veya bir hata nedeniyle kapandığında otomatik olarak devreye girecektir. Bu yöntem, bildirim sisteminizin kesintisiz çalışması için endüstri standardıdır.

Performans İzleme ve İleri İpuçları

WebSocket sunucunuz binlerce kullanıcıya ulaştığında, bellek yönetimi kritik bir hal alır. PHP'nin doğası gereği, uzun süre çalışan scriptlerde bellek sızıntıları (memory leaks) oluşabilir. Performansı optimize etmek için şu adımları izleyin:

  • Bellek Yönetimi: Gereksiz nesneleri unset() ile bellekten temizleyin.
  • Event Loop Optimizasyonu: Ratchet, ReactPHP tabanlıdır. Çok sayıda bağlantı için ev veya uv gibi daha hızlı event loop kütüphanelerini sunucunuza kurun.
  • Yük Dengeleme: Eğer kullanıcı sayınız çok yüksekse, tek bir sunucu yerine Redis Pub/Sub kullanarak WebSocket sunucularınızı yatayda ölçeklendirin (Horizontal Scaling).

Aşağıdaki basit örnek, Redis kullanarak farklı sunucular arasında mesajlaşma köprüsü kurmanın mantığını gösterir:

// Redis üzerinden mesaj yayınlama (Publisher)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->publish('notifications', json_encode(['user_id' => 5, 'msg' => 'Yeni bir mesajınız var!']));

// WebSocket sunucusu tarafında dinleme (Subscriber)
$loop->addPeriodicTimer(0.1, function() use ($redis, $clients) {
    $msg = $redis->get('notifications');
    if ($msg) {
        // İlgili istemciye gönder...
    }
});

Sonuç

PHP ile WebSocket kullanarak gerçek zamanlı bir bildirim sistemi kurmak, uygulamanızın etkileşim kapasitesini ciddi oranda artırır. Bu rehberde Ratchet kütüphanesini kullanarak temel bir mimariyi nasıl inşa edeceğinizi, istemci tarafında nasıl dinleyeceğinizi ve güvenlik süreçlerini öğrendiniz. Bir sonraki adım olarak, Redis kullanarak WebSocket sunucunuzu ölçeklenebilir hale getirebilir ve farklı sunucular arasında mesajlaşma sağlayabilirsiniz.

Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce tüm girdileri doğrulamalı, yetkilendirme (authentication) mekanizmaları eklemeli ve sunucu güvenliğini profesyonel standartlara göre yapılandırmalısınız.

Bu yazıya tepkinizi paylaşın:
Pelin Aydın

Kullanıcı deneyimi odaklı içerik stratejileri geliştiriyorum. Pratik bilgi arayan okuyucular için en hızlı ve etkili yöntemleri içeren rehberler hazırlıyorum.

Yorumlar (0)

Yorum Yaz