Rails'te Action Cable ve WebSocket'ler: Teknik Mulakat Rehberi 2026

Ruby on Rails'te Action Cable ve WebSocket'lerin derinlemesine incelenmesi. Bağlantılar, kanallar, broadcasting, Rails 8'de Solid Cable, Redis ile ölçeklendirme ve kod örnekleriyle sık sorulan mülakat soruları.

Ruby on Rails'te Action Cable ve WebSocket'ler hakkında derinlemesine inceleme

Action Cable, WebSocket desteğini doğrudan Rails framework'üne entegre ederek sohbet, bildirimler ve canlı panolar gibi gerçek zamanlı özelliklerin harici bağımlılıklar olmadan oluşturulmasını sağlar. 2026 teknik mülakatlarında Action Cable'ın iç mekanizmalarını — bağlantı yaşam döngüsünden üretim ortamında ölçeklendirmeye kadar — bilmek, güçlü adayları diğerlerinden ayıran önemli bir faktördür.

Mülakatlar için Temel Bilgi

Action Cable, WebSocket'leri kontrolcüler ve modeller için kullanılan aynı konvansiyonlarla Rails framework'üne entegre eder. Rails 8, pub/sub mesajlaşması için Redis gereksinimini ortadan kaldıran veritabanı destekli bir adaptör olan Solid Cable'ı tanıtır.

Rails Bağlamında WebSocket Protokolü Temelleri

WebSocket protokolü (RFC 6455), tek bir TCP bağlantısı üzerinden kalıcı, çift yönlü bir iletişim kanalı oluşturur. HTTP'nin istek-yanıt döngüsünün aksine, WebSocket'ler açık bir bağlantı sürdürerek hem istemcinin hem de sunucunun herhangi bir anda mesaj göndermesine olanak tanır.

Action Cable bu protokolü Rails'e uygun bir soyutlamaya dönüştürür. Sunucu, /cable adresinde WebSocket yükseltmelerini yönetir, bağlantı kimlik doğrulamasını kontrol eder ve mesajları kanallar üzerinden yönlendirir. İstemci tarafındaki JavaScript kütüphanesi abonelikleri otomatik olarak oluşturur ve yönetir.

Tipik bir HTTP isteği milisaniyeler içinde tamamlanır ve kapanır. WebSocket bağlantısı ise dakikalarca, saatlerce veya tüm oturum boyunca açık kalır. Bu temel fark, Action Cable'daki her mimari kararı belirler.

Action Cable Mimarisi: Bağlantılar, Kanallar ve Abonelikler

Action Cable, üç temel soyutlamaya sahip katmanlı bir mimari izler: bağlantılar kimlik doğrulamayı yönetir, kanallar iş mantığını kapsüller ve abonelikler tüketicileri belirli kanallara bağlar.

ruby
# app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      # Cookies are available in WebSocket handshake
      if verified_user = User.find_by(id: cookies.encrypted[:user_id])
        verified_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

Bağlantı sınıfı, WebSocket el sıkışması sırasında bir kez çalışır. Kimlik doğrulama burada gerçekleşir — bireysel kanallarda değil. identified_by bildirimi kullanıcı kimliğini kaydederek o bağlantıdaki tüm kanal aboneliklerinde erişilebilir kılar.

ruby
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    room = ChatRoom.find(params[:room_id])
    # Authorization: verify user belongs to this room
    if room.members.include?(current_user)
      stream_for room
    else
      reject
    end
  end

  def receive(data)
    message = ChatMessage.create!(
      room_id: params[:room_id],
      user: current_user,
      body: data["body"]
    )
    ChatChannel.broadcast_to(
      message.room,
      { id: message.id, body: message.body, user: current_user.name }
    )
  end

  def unsubscribed
    # Cleanup: mark user as offline
    AppearanceTracker.mark_offline(current_user)
  end
end

Kanallar üç yaşam döngüsü callback'i tanımlar: subscribed, receive ve unsubscribed. stream_for metodu aboneliği belirli bir model örneğine bağlayarak isim alanlı bir akış oluşturur. Bu akışa yapılan broadcast, bağlı her aboneye mesajları iletir.

JavaScript ile İstemci Tarafı Abonelikler

İstemci tarafındaki tüketici, Action Cable sunucusuna bağlanır ve abonelikleri yönetir. Her abonelik, sunucu tarafındaki bir kanala karşılık gelir.

app/javascript/channels/chat_channel.jsjavascript
import consumer from "./consumer"

const chatChannel = consumer.subscriptions.create(
  { channel: "ChatChannel", room_id: roomId },
  {
    connected() {
      // Called when the subscription is ready
      console.log("Connected to chat room", roomId)
    },

    disconnected() {
      // Called when the subscription is closed
      console.log("Disconnected from chat room")
    },

    received(data) {
      // Called when data is broadcast to the channel
      const messageList = document.getElementById("messages")
      messageList.insertAdjacentHTML("beforeend",
        `<div class="message"><strong>${data.user}</strong>: ${data.body}</div>`
      )
    },

    sendMessage(body) {
      // Calls ChatChannel#receive on the server
      this.perform("receive", { body: body })
    }
  }
)

received callback'i, sunucu abone olunan akışa her broadcast yaptığında tetiklenir. perform metodu istemciden sunucuya veri göndererek ilgili kanal metodunu çağırır.

Ruby on Rails mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Rails 8'de Solid Cable: Veritabanı Destekli Pub/Sub

Rails 8, Solid Queue ve Solid Cache ile birlikte "Solid Trifecta"nın bir parçası olarak Solid Cable'ı sunar. Solid Cable, mesajları bir veritabanı tablosunda depolayarak Redis'in yerine pub/sub arka ucu olarak görev yapar.

yaml
# config/cable.yml (Rails 8 default)
development:
  adapter: solid_cable

production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds
  message_retention: 1.day

Solid Cable, her broadcast mesajını bir veritabanı tablosuna yazarak ve yapılandırılabilir bir aralıkta yeni mesajları sorgulayarak çalışır. Varsayılan 100ms'lik sorgulama aralığı, çoğu uygulama için neredeyse gerçek zamanlı teslimat sağlar.

Ödünleşim açıktır: Solid Cable bir altyapı bağımlılığını (Redis) ortadan kaldırırken, biraz daha yüksek gecikme ve veritabanı yükü getirir. Zaten PostgreSQL veya MySQL kullanan uygulamalar için bu ödünleşim genellikle mantıklıdır. Yüksek frekanslı broadcasting (saniyede binlerce mesaj) için Redis daha iyi bir seçim olmaya devam eder.

ruby
# config/database.yml (Rails 8 multi-database)
production:
  primary:
    <<: *default
    database: myapp_production
  cable:
    <<: *default
    database: myapp_cable_production
    migrations_paths: db/cable_migrate

Solid Cable, birincil veritabanı ile çakışmayı önlemek için ayrılmış bir veritabanı kullanır. Bu ayrım, mesaj sorgulamasının uygulama sorgularını etkilemesini önler.

Broadcasting Kalıpları ve Sunucu Tarafı Tetikleyiciler

Modeller, arka plan görevleri ve kontrolcülerden broadcasting, üretim Rails uygulamalarında en yaygın üç kalıbı kapsar.

ruby
# Broadcasting from a model callback
class Notification < ApplicationRecord
  belongs_to :user
  after_create_commit :broadcast_to_user

  private

  def broadcast_to_user
    ActionCable.server.broadcast(
      "notifications_#{user_id}",
      { id: id, title: title, read: false }
    )
  end
end

# Broadcasting from a background job
class DashboardUpdateJob < ApplicationJob
  queue_as :default

  def perform(dashboard_id)
    dashboard = Dashboard.find(dashboard_id)
    stats = dashboard.compute_stats
    ActionCable.server.broadcast(
      "dashboard_#{dashboard_id}",
      { stats: stats, updated_at: Time.current.iso8601 }
    )
  end
end

Model callback'leri, kayıt değişiklikleriyle tetiklenen basit bildirimler için uygundur. Arka plan görevleri ise daha ağır hesaplamaları — pano istatistiklerinin hesaplanması veya verilerin toplanması gibi — istek döngüsünü engellemeden yönetir. Broadcast'in kendisi her zaman hafiftir: payload'ı serileştirir ve adaptöre yayınlar.

Turbo Streams ve Action Cable Entegrasyonu

Hotwire ile Rails 8, Turbo Streams için taşıma katmanı olarak Action Cable'ı kullanarak özel JavaScript yazmadan gerçek zamanlı DOM güncellemeleri yapılmasını sağlar.

ruby
# app/models/message.rb
class Message < ApplicationRecord
  belongs_to :chat_room
  # Automatically broadcasts append to subscribers
  broadcasts_to :chat_room
end

# app/views/chat_rooms/show.html.erb
<%= turbo_stream_from @chat_room %>
<div id="messages">
  <%= render @chat_room.messages %>
</div>

broadcasts_to makrosu, Turbo Stream fragmanlarını Action Cable üzerinden broadcast eden after_create, after_update ve after_destroy callback'leri oluşturur. İstemci tarafındaki turbo_stream_from helper'ı eşleşen akışa abone olur. Yeni bir mesaj oluşturulduğunda, render edilmiş partial otomatik olarak bağlı her istemcinin DOM'una eklenir.

Bu kalıp, gerçek zamanlı özellikleri bir model bildirimi ve bir view helper'ına indirger — özel kanallar, JavaScript handler'ları veya manuel DOM manipülasyonu gerekmez.

Üretim Ortamında Action Cable'ı Ölçeklendirme

Üretim dağıtımları, adaptör seçimi, bağlantı limitleri ve yatay ölçeklendirme konularında dikkatli değerlendirme gerektirir.

ruby
# config/cable.yml — Redis adapter for high-scale production
production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: myapp_production

Redis, pub/sub omurgası olarak görev yapar ve bir Rails sürecinde yayınlanan mesajların diğer herhangi bir sürece bağlı abonelere ulaşmasını sağlar. Redis (veya Solid Cable) olmadan, async adaptör broadcasting'i tek bir süreçle sınırlar — bu da çoklu süreç veya çoklu sunucu dağıtımlarında kullanılamaz.

Bağlantı limitleri sunucuya bağlıdır. Action Cable ile Puma, WebSocket bağlantılarını HTTP istekleriyle aynı süreçte yönetir. Her WebSocket kalıcı bir bağlantı tutar ve bir iş parçacığı (veya Ruby 3.x'te fiber tabanlı zamanlayıcılarla bir fiber) tüketir. 5 iş parçacığı ve 4 worker'lı tipik bir Puma yapılandırması, doygunluktan önce yaklaşık 200 eşzamanlı WebSocket bağlantısını yönetebilir.

Binlerce eşzamanlı bağlantı gerektiren uygulamalar için AnyCable, Ruby WebSocket sunucusunun yerini Go tabanlı bir sunucu ile alır. Bağlantıları protokol düzeyinde yönetirken kanal mantığını gRPC aracılığıyla Rails'e geri yönlendirir. Bu mimari, düğüm başına 10.000'den fazla eşzamanlı bağlantıyı destekler.

Mülakat Bilgisi

Mülakatçılar sıklıkla Action Cable ölçeklendirme limitleri hakkında soru sorar. Anahtar cevap: Action Cable'ın kendisi darboğaz değildir — darboğaz, WebSocket bağlantılarını yöneten Ruby sürecidir. AnyCable, bağlantı yönetimini Go'ya taşıyarak ve kanal mantığını Ruby'de tutarak bu sorunu çözer.

Action Cable Kanallarını Test Etme

Rails, kanalların birim testi için ActionCable::Channel::TestCase ve bağlantı kimlik doğrulaması için ActionCable::Connection::TestCase sağlar.

ruby
# test/channels/chat_channel_test.rb
require "test_helper"

class ChatChannelTest < ActionCable::Channel::TestCase
  test "subscribes to a valid room" do
    room = chat_rooms(:general)
    user = users(:alice)
    stub_connection current_user: user

    subscribe room_id: room.id

    assert subscription.confirmed?
    assert_has_stream_for room
  end

  test "rejects subscription for unauthorized user" do
    room = chat_rooms(:private)
    user = users(:outsider)
    stub_connection current_user: user

    subscribe room_id: room.id

    assert subscription.rejected?
  end

  test "broadcasts messages to room subscribers" do
    room = chat_rooms(:general)
    stub_connection current_user: users(:alice)
    subscribe room_id: room.id

    assert_broadcast_on(room, hash_including(body: "Hello")) do
      perform :receive, body: "Hello"
    end
  end
end

stub_connection metodu, gerçek bir WebSocket olmadan bağlantı bağlamını kurar. assert_has_stream_for akış bağlamasını doğrular. assert_broadcast_on bir blok içindeki broadcast'leri yakalar ve doğru payload'ın doğru akışa ulaştığını onaylar.

Action Cable Hakkında Sık Sorulan Mülakat Soruları

Action Cable hakkındaki teknik mülakat soruları genellikle protokol anlayışını, mimari kararları ve üretim ortamı endişelerini araştırır.

Action Cable bağlantıları nasıl doğrular? Kimlik doğrulama, WebSocket el sıkışması sırasında ApplicationCable::Connection#connect metodunda gerçekleşir. Bu noktada HTTP oturumundan gelen çerezler mevcuttur. Token tabanlı kimlik doğrulama, token'ı WebSocket URL'sinde sorgu parametresi olarak iletir ve connect metodunda doğrular.

WebSocket bağlantısı koptuğunda ne olur? İstemci kütüphanesi, üstel geri çekilme ile otomatik yeniden bağlantı uygular. Sunucu tarafında, bağlantının abone olduğu her kanal için unsubscribed tetiklenir. Durum bilgisi içeren temizlik (kullanıcıları çevrimdışı olarak işaretleme, kilitleri serbest bırakma) unsubscribed metoduna yerleştirilmelidir.

Solid Cable ne zaman Redis yerine tercih edilmelidir? Solid Cable, Redis altyapısından kaçınmak isteyen orta düzey gerçek zamanlı ihtiyaçları olan uygulamalar (saniyede 100'den az mesaj) için uygundur. Yüksek verimlilik senaryolarında veya 10ms altı teslimat gecikmesinin önemli olduğu durumlarda Redis gerekli olmaya devam eder.

Sık Yapılan Hata

Yetkilendirme mantığının bireysel kanallar yerine bağlantı sınıfına yerleştirilmesi. Bağlantı kimliği doğrular (bu kullanıcı kim?). Kanallar erişimi yetkilendirir (bu kullanıcı bu odaya erişebilir mi?). Bu sorumlulukların karıştırılması güvenlik açıkları oluşturur.

Sonuc

  • Action Cable, WebSocket protokolünü bağlantılar, kanallar ve abonelikler ile Rails konvansiyonlarına sarar
  • Kimlik doğrulama ApplicationCable::Connection'a aittir; yetkilendirme bireysel kanal subscribed callback'lerine aittir
  • Rails 8'deki Solid Cable, pub/sub için veritabanını kullanarak Redis bağımlılığını ortadan kaldırır — orta verimli uygulamalar için uygundur
  • Turbo Streams, minimum kodla otomatik gerçek zamanlı DOM güncellemeleri için Action Cable'ı kullanır
  • Üretim ölçeklendirmesi, çoklu süreç dağıtımları için Redis veya Solid Cable gerektirir; AnyCable, WebSocket yönetimini Go'ya taşıyarak 10.000'den fazla bağlantıyı destekler
  • Kanal testi stub_connection, assert_has_stream_for ve assert_broadcast_on kullanır — gerçek WebSocket bağlantıları gerekmez
  • Action Cable ve WebSocket mülakat sorularını pratik yaparak bu kavramları hedefli alıştırmalarla pekiştirmek mümkündür

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Etiketler

#ruby on rails
#action cable
#websockets
#real-time
#solid cable
#rails 8

Paylaş

İlgili makaleler