Gerçek Zamanlı İletişimin Kalbi: WebSocket’ler ve Uygulama Tasarımı

Günümüz dijital dünyasında anlık mesajlaşma uygulamaları, canlı sohbetler, veri akışları ve online oyunlar gibi gerçek zamanlı etkileşimler hayatımızın vazgeçilmez bir parçası haline geldi. Peki, WhatsApp’ta attığınız bir mesaj veya bir canlı yayın sohbetinde yazdığınız yorum anında nasıl karşı tarafa ulaşıyor? Bu hızlı ve kesintisiz iletişimin arkasında yatan temel teknolojilerden biri de **WebSocket**’lerdir. Geleneksel HTTP isteklerinin ötesine geçerek iki yönlü, kalıcı bir bağlantı sunan WebSockets, modern uygulamaların temel taşlarından biri.

Bir sistem tasarım mülakatında gerçek zamanlı bir mesajlaşma uygulaması tasarlarken karşılaşılan zorluklar, bu derinlemesine incelemeye ilham verdi. Bu makalede, WebSocket’lerin istemci-sunucu iletişimi içindeki yerini, neyi iyi yaptıklarını, nerede yetersiz kaldıklarını ve evet, gerçek zamanlı bir mesajlaşma uygulamasını nasıl tasarlayacağınızı keşfedeceğiz. Böylece, benzer hatalardan kaçınabilir ve daha sağlam sistemler inşa edebilirsiniz.

İstemci-Sunucu İletişiminin Temelleri

Özünde, istemci-sunucu iletişimi, iki varlık (bir istemci ve bir sunucu) arasında veri alışverişidir. İstemci veri talep ederken, sunucu bu istekleri işler ve bir yanıt döndürür. Ancak, bu roller sabit değildir; hizmetler bağlama göre hem istemci hem de sunucu olarak aynı anda hareket edebilir.

WebSocket’lerin ayrıntılarına dalmadan önce, istemci-sunucu iletişim yöntemlerinin daha büyük resmine bir göz atalım. Bu yöntemler, genellikle tek yönlü veri akışına odaklanır ve gerçek zamanlı, iki yönlü iletişimde bazı sınırlamalara sahiptir.

Geleneksel İletişim Yöntemleri ve Sınırlamaları

Gerçek zamanlı iletişime giden yolda farklı yaklaşımlar bulunmaktadır. Her birinin kendine özgü avantajları ve dezavantajları vardır:

Kısa Yoklama (Short Polling)

En basit ve tanıdık yaklaşımdır. İstemci, yeni veri olup olmadığını kontrol etmek için düzenli aralıklarla (örneğin, her birkaç saniyede bir) sunucuya HTTP istekleri gönderir. Her istek bağımsız ve tek yönlüdür (istemci → sunucu). Kurulumu kolaydır ancak sunucuda nadiren yeni veri varsa kaynak israfına yol açabilir. Daha az zaman hassasiyeti olan uygulamalar için uygundur.

Uzun Yoklama (Long Polling)

Kısa yoklamaya göre bir iyileştirmedir ve gereksiz istek sayısını azaltmak için tasarlanmıştır. Sunucu, istemci isteğine hemen yanıt vermek yerine, yeni veri gelene kadar bağlantıyı açık tutar. Sunucuda veri olduğunda yanıtı gönderir ve istemci hemen yeni bir bağlantı kurar. Uzun yoklama da durumsuz ve tek yönlüdür (istemci → sunucu).

Webhook’lar

Webhook’lar, sunucuyu başlatıcı yaparak senaryoyu değiştirir. Sunucu, belirli olaylar meydana geldiğinde istemci tarafından tanımlanan bir uç noktaya HTTP POST istekleri gönderir. Her istek bağımsızdır ve kalıcı bir bağlantıya dayanmaz. Webhook’lar da tek yönlüdür (sunucu → istemci). Özellikle üçüncü taraf hizmetlerle entegrasyon yaparken asenkron bildirimler için yaygın olarak kullanılır.

Sunucu Tarafından Gönderilen Olaylar (Server-Sent Events – SSE)

SSE’ler, sunucuların tek, kalıcı bir bağlantı üzerinden istemcilere gerçek zamanlı güncellemeler göndermesine olanak tanıyan yerel bir HTTP tabanlı olay akışı protokolüdür. EventSource API’sini kullanarak çalışır ve modern web uygulamalarında uygulanması basittir. Tek yönlüdür (sunucu → istemci) ve istemcinin yalnızca güncelleme alması gereken durumlar için idealdir. Ancak tüm bu yöntemler tek yönlü bir veri akışına odaklanır. Gerçek iki yönlü, gerçek zamanlı alışverişler için farklı bir yaklaşıma ihtiyacımız var: WebSocket’ler.

WebSocket’ler Nasıl Çalışır?

WebSocket’ler, gerçek zamanlı, çift yönlü iletişimi mümkün kılarak sohbet uygulamaları, canlı bildirimler ve çevrimiçi oyunlar gibi uygulamalar için mükemmel bir çözüm sunar. Geleneksel HTTP istek-yanıt modelinden farklı olarak, WebSocket’ler kalıcı bir bağlantı oluşturur. Bu sayede hem istemci hem de sunucu, bir istek beklemeksizin bağımsız olarak mesaj gönderebilir.

Bağlantı, normal bir HTTP isteği olarak başlar ve bir el sıkışma (handshake) ile WebSocket bağlantısına yükseltilir. Kurulduktan sonra, HTTP ile aynı bağlantı noktalarında (80 ve 443) tek bir TCP bağlantısı kullanır. WebSocket’ler üzerinden gönderilen mesajlar küçük ve hafiftir, bu da onları düşük gecikmeli, yüksek etkileşimli kullanım durumları için verimli hale getirir.

WebSocket bağlantıları, düzenli bağlantılar için ws:// ve güvenli, şifreli bağlantılar için wss:// olmak üzere belirli bir URI formatını takip eder. El sıkışma, iki sistem arasında bir bağlantıyı başlatma sürecidir. WebSocket’ler için, istemciden protokol yükseltmesi isteyen bir HTTP GET isteğiyle başlar. Bu, kalıcı bir WebSocket bağlantısına geçiş yapmadan önce HTTP altyapısıyla uyumluluğu sağlar.

WebSocket Kullanım Alanları

WebSocket’lerin gerçek zamanlı, çift yönlü iletişimi nasıl sağladığından bahsettik, ancak bu hala soyut bir terim. Bazı somut örneklere bakalım. WebSocket’ler, Excalidraw, Telegram, WhatsApp, Google Docs, Google Haritalar gibi gerçek zamanlı işbirliği araçlarında ve sohbet uygulamalarında, ayrıca YouTube veya TikTok canlı yayınlarındaki canlı sohbet bölümlerinde yaygın olarak kullanılır. Canlı güncellemeler, çok oyunculu oyunlar ve finansal ticaret platformları gibi alanlarda da vazgeçilmezdirler.

WebSocket’lerin Ticari Dengeleri ve Zorlukları

Her teknolojide olduğu gibi, WebSocket’lerin de bazı ödünleşimleri ve zorlukları vardır:

Bağlantı Kesintisi Durumunda Yedek Stratejisi

Ağ sorunları, sunucu çökmeleri veya diğer hatalar nedeniyle bağlantı kesilirse, WebSocket’ler otomatik olarak kurtulmaz. İstemcinin bağlantı kesilmesini açıkça algılaması ve bağlantıyı yeniden kurmaya çalışması gerekir. Genellikle bir WebSocket bağlantısı yeniden kurulmaya çalışılırken uzun yoklama bir yedek olarak kullanılır.

Ses ve Video Verisi Akışı İçin Optimize Edilmemiş

WebSocket mesajları, küçük, yapılandırılmış mesajlar göndermek için tasarlanmıştır. Büyük medya verilerini akışla göndermek için, WebRTC gibi teknolojiler bu senaryolar için daha uygundur.

WebSocket’ler Durumludur, Bu Nedenle Yatay Ölçekleme Zorludur

WebSocket’ler durumlu (stateful) olduğundan, sunucunun her istemci için aktif bir bağlantıyı sürdürmesi gerekir. Bu durum, herhangi bir sunucunun kalıcı bir durumu sürdürmeden bir istemci isteğini işleyebildiği durumsuz HTTP’ye kıyasla yatay ölçeklemeyi daha karmaşık hale getirir. Bunu yapmak için ek bir yayın/abone (pub/sub) mekanizması katmanına ihtiyacınız olacaktır.

Gerçek Zamanlı Bir Mesajlaşma Uygulaması Tasarımı

Şimdi bu bilgilerin sistem tasarımında nasıl uygulandığını görelim. Hem basit (ölçeklenemeyen) çözümü hem de yatay olarak ölçeklenmiş bir çözümü ele alalım.

Yatay Ölçeklenmiş Sistem: İki Kullanıcı Gerçek Zamanlı Nasıl Sohbet Eder?

Tek bir sunucu belirli sayıda eşzamanlı WebSocket’i işleyebilir. Daha fazla kullanıcıya hizmet vermek için WebSocket bağlantılarınızı yatay olarak ölçeklendirmeniz gerekir. Buradaki temel zorluk şudur: Eğer kullanıcı1 sunucu1’e bağlıysa, ancak kullanıcı2 sunucu2’ye bağlıysa, sistem mesajı nereye göndereceğini nasıl bilir?

Redis, aktif WebSocket oturumları için kullanıcı kimliği (userID) ile sunucu kimliğini (serverID) eşleştiren global bir veri deposu olarak kullanılabilir. Her sunucu, bir kullanıcı bağlandığında (çevrimiçi olduğunda) veya bağlantısı kesildiğinde (çevrimdışı olduğunda) Redis’i günceller.

Uçtan uca sohbet akışı şu şekilde işler: kullanıcı1, sunucu1 üzerindeki WebSocket’i aracılığıyla bir mesaj gönderir. Sunucu1 mesajı bir Sohbet Servisi’ne (Chat Service) iletir. Sohbet Servisi, kalıcılık için mesajı önce Mesaj Veritabanı’na (MessageDB) yazar. Ardından, Sohbet Servisi, kullanıcı2’nin çevrimiçi/çevrimdışı durumunu Redis’ten kontrol eder.

Eğer kullanıcı2 çevrimiçiyse, Sohbet Servisi mesajı bir mesaj aracıcısına (message broker) yayınlar ve bunu “kullanıcı2: sunucu2” etiketiyle işaretler. Aracı, mesajı sunucu2’ye yönlendirir. Sunucu2, kullanıcı2’nin WebSocket bağlantısını bulmak için yerel bellek içi eşlemesine bakar ve mesajı o WebSocket üzerinden gerçek zamanlı olarak iletir. Eğer kullanıcı2 çevrimdışıysa (Redis’te giriş yoksa), Sohbet Servisi mesajı Gelen Kutusu Veritabanı’na (InboxDB) yazar. Kullanıcı2 çevrimiçi olduğunda, Sohbet Servisi teslim edilmemiş tüm mesajları getirir.

Önemli Tasarım Hususları

Böylesine bir sistemi tasarlarken göz önünde bulundurulması gereken bazı kritik noktalar vardır:

  • Önce Kalıcılık: Tüm mesajlar teslim edilmeden önce veritabanına kaydedilir. WebSocket’e bir gönderme başarısız olursa, mesaj veritabanında güvende kalır.
  • Redis: Yalnızca aktif bağlantıları saklayarak ek yükü en aza indirir. Tek hata noktasını önlemek için bir replika eklenebilir. Inbox DB, çevrimdışı durumları sorunsuz bir şekilde ele almaya yardımcı olur.
  • Sohbet Servisi Soyutlaması: WebSocket sunucuları gerçek zamanlı bağlantıları ve yönlendirmeyi yönetir. Sohbet Servisi katmanı ise HTTP isteklerini ve tüm veritabanı yazımlarını ele alır. Bu görev ayrımı, her bir parçayı ölçeklendirmeyi veya geliştirmeyi kolaylaştırır.
  • Mesajların Sıralı Teslimatını Sağlama: Tipik “gerçek zamanlı itme” iş akışları, ağ varyasyonları nedeniyle mesajların sırasız gelmesine neden olabilir. Birçok mesaj aracısı da kesin sıralama garantisi vermez. Bunu ele almak için, her mesaja oluşturulduğu anda bir zaman damgası atanır. Mesajlar sırasız gelse bile, istemci bunları zaman damgasına göre yeniden sıralayabilir.
  • Yük Dengeleyiciler: Yapışkan WebSocket bağlantıları için L4 Yük Dengeleyici (TCP) ve düzenli istekler (CRUD, giriş vb.) için L7 Yük Dengeleyici (HTTP) kullanılır.

WebSocket’ler, modern gerçek zamanlı uygulamaların temelini oluşturan güçlü ve esnek bir iletişim protokolüdür. İki yönlü, düşük gecikmeli bağlantılar sunarak kullanıcı deneyimini zenginleştirirler. Ancak, bu gücü kullanırken, ölçeklenebilirlik, hata toleransı ve veri tutarlılığı gibi tasarım zorluklarını akılda tutmak önemlidir. Redis gibi araçları ve iyi yapılandırılmış servis katmanlarını kullanarak, milyonlarca kullanıcıya hizmet verebilecek sağlam ve yüksek performanslı gerçek zamanlı sistemler inşa edebilirsiniz. Gelecekteki projelerinizde bu bilgileri değerlendirerek, kullanıcılarınıza kesintisiz ve anlık bir deneyim sunmanız mümkün olacaktır.

Yorum Gönderin

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Exit mobile version