ASP.NET Core 2026'da SignalR: Gerçek Zamanlı İletişim, Hub'lar ve Mülakat Soruları

ASP.NET Core'da SignalR için kapsamlı rehber. Gerçek zamanlı iletişim, hub yapılandırması, grup yönetimi ve mülakat hazırlığı konularını öğrenin.

ASP.NET Core'da SignalR - gerçek zamanlı iletişim

SignalR, ASP.NET Core uygulamalarında sunucular ve istemciler arasında çift yönlü gerçek zamanlı iletişim sağlar. Geleneksel HTTP istek-yanıt modelinin aksine, SignalR sunucuların güncellemeleri istemcilere anında göndermesine olanak tanıyan kalıcı bağlantılar sürdürür—sohbet uygulamaları, canlı kontrol panelleri, ortak düzenleme ve gerçek zamanlı bildirimler için vazgeçilmezdir.

SignalR Transport Yedekleme Mekanizması

SignalR otomatik olarak mevcut en iyi transport'u seçer: önce WebSockets, ardından Server-Sent Events, son olarak Long Polling. Bu yedekleme mekanizması, herhangi bir kod değişikliği yapmadan tüm tarayıcılar ve ağ yapılandırmalarıyla uyumluluk sağlar.

SignalR Hub'ları Sunucu-İstemci İletişimini Nasıl Sağlar

Hub, istemciler ve sunucular arasındaki metot çağrılarını yöneten üst düzey bir pipeline görevi görür. İstemciler hub üzerindeki metotları çağırır ve hub bağlı istemciler üzerindeki metotları çağırabilir. Bu soyutlama, WebSocket bağlantılarını manuel olarak yönetme karmaşıklığını ortadan kaldırır.

Aşağıdaki örnek, mesajları tüm bağlı istemcilere yayınlayan temel bir sohbet hub'ını gösterir:

ChatHub.cscsharp
using Microsoft.AspNetCore.SignalR;

public class ChatHub : Hub
{
    // İstemci mesaj gönderdiğinde çağrılır
    public async Task SendMessage(string user, string message)
    {
        // TÜM bağlı istemcilere yayınla
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }

    // İstemci bağlandığında otomatik çağrılır
    public override async Task OnConnectedAsync()
    {
        await Clients.Caller.SendAsync("Connected", Context.ConnectionId);
        await base.OnConnectedAsync();
    }

    // İstemci bağlantısı kesildiğinde otomatik çağrılır
    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        // Kaynakları temizle, diğer kullanıcıları bilgilendir, vb.
        await base.OnDisconnectedAsync(exception);
    }
}

Clients özelliği, çeşitli hedefleme seçenekleri aracılığıyla tüm bağlı istemcilere erişim sağlar: All, Caller, Others, Group ve User.

ASP.NET Core 9'da SignalR Yapılandırması

ASP.NET Core 9'da SignalR kaydı standart middleware desenini takip eder. Aşağıdaki yapılandırma, özel buffer boyutlarıyla JSON ve MessagePack protokollerini etkinleştirir:

Program.cscsharp
var builder = WebApplication.CreateBuilder(args);

// Yapılandırmayla SignalR servislerini ekle
builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = builder.Environment.IsDevelopment();
    options.MaximumReceiveMessageSize = 64 * 1024; // 64 KB
    options.StreamBufferCapacity = 10;
    options.KeepAliveInterval = TimeSpan.FromSeconds(15);
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
})
.AddJsonProtocol(options =>
{
    options.PayloadSerializerOptions.PropertyNamingPolicy = null; // PascalCase
});

var app = builder.Build();

// Hub endpoint'ini eşle
app.MapHub<ChatHub>("/chathub");

app.Run();

KeepAliveInterval ve ClientTimeoutInterval ayarları bağlantı sağlık durumu izlemesini kontrol eder. Zaman aşımı süresi içinde yanıt vermeyen istemciler bağlantısı kesilmiş olarak kabul edilir.

Hedefli Mesaj Dağıtımı için Grup Yönetimi

Gruplar, bağlantıları organize etmek ve mesajları istemci alt kümelerine göndermek için bir mekanizma sağlar. Tipik bir kullanım durumu, kullanıcıların belirli odalara katıldığı ve yalnızca bu odalardan mesaj aldığı sohbet odalarıdır.

GroupChatHub.cscsharp
public class GroupChatHub : Hub
{
    // Mevcut bağlantıyı bir gruba ekle
    public async Task JoinRoom(string roomName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
        
        // Gruba birinin katıldığını bildir
        await Clients.Group(roomName).SendAsync(
            "UserJoined", 
            Context.User?.Identity?.Name ?? "Anonymous"
        );
    }

    // Mevcut bağlantıyı bir gruptan çıkar
    public async Task LeaveRoom(string roomName)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
        
        await Clients.Group(roomName).SendAsync(
            "UserLeft",
            Context.User?.Identity?.Name ?? "Anonymous"
        );
    }

    // Yalnızca belirli bir gruba mesaj gönder
    public async Task SendToRoom(string roomName, string message)
    {
        await Clients.Group(roomName).SendAsync(
            "ReceiveMessage",
            Context.User?.Identity?.Name,
            message
        );
    }
}

Grup üyeliği kullanıcılara değil bağlantılara bağlıdır. Kullanıcı yeniden bağlandığında gruplarına tekrar katılması gerekir. Kalıcı grup üyeliği için grup ilişkilerini veritabanında saklayın ve OnConnectedAsync'de otomatik olarak yeniden katılın.

Grup Kalıcılığı

Gruplar yalnızca bellekte bulunur ve backplane olmadan sunucu yeniden başlatmalarında veya ölçekleme senaryolarında kalıcı değildir. Birden fazla sunuculu üretim dağıtımları için backplane olarak Redis veya Azure SignalR Service kullanın.

Kimlik Doğrulama ile SignalR Bağlantılarını Güvence Altına Alma

SignalR, ASP.NET Core kimlik doğrulamasıyla entegre olur. [Authorize] özniteliği hub erişimini yalnızca kimliği doğrulanmış kullanıcılarla sınırlar ve Context.User kimliği doğrulanmış kullanıcının claim'lerine erişim sağlar.

SecureHub.cscsharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;

[Authorize] // Tüm hub için kimlik doğrulama gerektir
public class SecureHub : Hub
{
    // Context.User aracılığıyla kullanıcı claim'lerine eriş
    public async Task SendPrivateMessage(string recipientUserId, string message)
    {
        var senderName = Context.User?.Identity?.Name 
            ?? throw new HubException("User not authenticated");
        
        // Belirli bir kullanıcıya gönder (tüm bağlantılarına)
        await Clients.User(recipientUserId).SendAsync(
            "PrivateMessage",
            senderName,
            message
        );
    }

    [Authorize(Roles = "Admin")] // Metot üzerinde rol tabanlı yetkilendirme
    public async Task BroadcastAnnouncement(string announcement)
    {
        await Clients.All.SendAsync("Announcement", announcement);
    }
}

WebSocket bağlantıları için, WebSockets özel başlıkları desteklemediğinden kimlik doğrulama token'ları query string aracılığıyla iletilmelidir. JavaScript istemcisini token'ı içerecek şekilde yapılandırın:

signalr-client.tstypescript
import * as signalR from "@microsoft/signalr";

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/securehub", {
        accessTokenFactory: () => localStorage.getItem("authToken") || ""
    })
    .withAutomaticReconnect()
    .build();

await connection.start();

Sunucu tarafında, JWT kimlik doğrulamasını query string'den token okuyacak şekilde yapılandırın:

Program.cs - SignalR için JWT yapılandırmasıcsharp
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                // SignalR için query string'den token oku
                var accessToken = context.Request.Query["access_token"];
                var path = context.HttpContext.Request.Path;
                
                if (!string.IsNullOrEmpty(accessToken) && 
                    path.StartsWithSegments("/securehub"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
    });

.NET mülakatlarında başarılı olmaya hazır mısın?

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

Redis Backplane ile SignalR Ölçekleme

Yük dengelemeli bir ortamda, istemciler farklı sunucu örneklerine bağlanabilir. Backplane olmadan, bir sunucudan gönderilen mesajlar yalnızca o sunucuya bağlı istemcilere ulaşır. Redis, tüm sunucu örnekleri arasında mesajları senkronize etmek için backplane görevi görür.

Program.cs - Redis backplane yapılandırmasıcsharp
builder.Services.AddSignalR()
    .AddStackExchangeRedis(options =>
    {
        options.Configuration = builder.Configuration
            .GetConnectionString("Redis");
        
        // Opsiyonel: Redis'e özgü seçenekleri yapılandır
        options.Configuration.ChannelPrefix = 
            RedisChannel.Literal("MyApp_SignalR_");
    });

Redis backplane, tüm SignalR mesajlarını Redis kanallarına yayınlar. Her sunucu örneği bu kanallara abone olur ve mesajları yerel istemcilerine iletir. Bu yaklaşım, yatay ölçeklemeyi etkinleştirirken minimum gecikme ekler (genellikle 1-2ms).

Kurumsal dağıtımlar için, Azure SignalR Service ölçekleme, bağlantı yönetimi ve kullanılabilirliği otomatik olarak yöneten yönetilen bir alternatif sunar.

Derleme Zamanı Güvenliği için Güçlü Tipli Hub'lar

Güçlü tipli hub'lar, sihirli string'leri arayüz metotlarıyla değiştirerek istemci metot çağrılarının derleme zamanı doğrulamasını sağlar:

INotificationClient.cscsharp
public interface INotificationClient
{
    Task ReceiveNotification(string title, string message, string severity);
    Task UpdateProgress(int percentage);
    Task TaskCompleted(Guid taskId, bool success);
}

// NotificationHub.cs
public class NotificationHub : Hub<INotificationClient>
{
    public async Task NotifyAll(string title, string message)
    {
        // Derleme zamanı kontrolü - sihirli string yok
        await Clients.All.ReceiveNotification(title, message, "info");
    }

    public async Task ReportProgress(string groupName, int percentage)
    {
        // IDE otomatik tamamlama burada çalışır
        await Clients.Group(groupName).UpdateProgress(percentage);
    }
}

Refactoring daha güvenli hale gelir çünkü arayüzdeki bir metodu yeniden adlandırmak, güncellenmesi gereken tüm çağrı noktalarını anında gösterir.

SignalR Kanalları ile Veri Akışı

SignalR, ilerleme güncellemeleri, log takibi veya gerçek zamanlı sensör verileri gibi verilerin artımlı olarak üretildiği senaryolar için akışı destekler. Hem sunucudan istemciye hem de istemciden sunucuya akış desteklenir.

StreamingHub.cscsharp
public class StreamingHub : Hub
{
    // IAsyncEnumerable ile sunucudan istemciye akış
    public async IAsyncEnumerable<StockPrice> StreamStockPrices(
        string[] symbols,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        var random = new Random();
        
        while (!cancellationToken.IsCancellationRequested)
        {
            foreach (var symbol in symbols)
            {
                yield return new StockPrice
                {
                    Symbol = symbol,
                    Price = random.NextDouble() * 1000,
                    Timestamp = DateTime.UtcNow
                };
            }
            
            await Task.Delay(1000, cancellationToken);
        }
    }

    // İstemciden sunucuya akış
    public async Task UploadStream(IAsyncEnumerable<LogEntry> stream)
    {
        await foreach (var entry in stream)
        {
            // Her log girişini geldiğinde işle
            await ProcessLogEntry(entry);
        }
    }
}

public record StockPrice(string Symbol, double Price, DateTime Timestamp);
public record LogEntry(string Level, string Message, DateTime Timestamp);

JavaScript istemcisi akışı async iterator kullanarak tüketir:

streaming-client.tstypescript
const stream = connection.stream("StreamStockPrices", ["AAPL", "MSFT"]);

stream.subscribe({
    next: (price) => console.log(`${price.symbol}: $${price.price}`),
    error: (err) => console.error(err),
    complete: () => console.log("Stream completed")
});

Yaygın SignalR Mülakat Soruları

Teknik mülakatlar sıklıkla SignalR mimarisi ve gerçek dünya senaryolarını kapsar. Aşağıdaki sorular .NET mülakat oturumlarında düzenli olarak karşılaşılır:

Mülakat İpucu

Transport müzakere sürecini açıklayın: SignalR önce WebSockets'i dener, ardından Server-Sent Events'e, sonra Long Polling'e geçer. Her transport'un ne zaman kullanıldığını ve sınırlamalarını anlayın.

S: SignalR, istemci geçici olarak bağlantı kaybettiğinde bağlantı durumunu nasıl yönetir?

SignalR, sunucuda bağlantı durumunu yapılandırılabilir bir süre boyunca korur. Otomatik yeniden bağlanma etkinleştirildiğinde, istemci aynı bağlantı kimliğini kullanarak yeniden bağlanmayı dener. Başarılı olursa, bağlantı grup üyeliklerini kaybetmeden devam eder. Bağlantı kesintisi zaman aşımını aşarsa, yeni bir bağlantı kurulur ve istemcinin gruplara yeniden katılması gerekir.

S: Clients.User() ile Clients.Client() arasındaki fark nedir?

Clients.User(userId) belirli bir kimliği doğrulanmış kullanıcıya ait tüm bağlantıları hedefler—bir kullanıcının birden fazla tarayıcı sekmesi açık olduğunda kullanışlıdır. Clients.Client(connectionId) tek bir belirli bağlantıyı hedefler. Kullanıcı tabanlı hedefleme, kimlik doğrulama gerektirir ve bağlantıları kullanıcı kimliklerine eşlemek için IUserIdProvider kullanır.

S: Çevrimiçi durumu algılama (kimin çevrimiçi olduğunu gösterme) nasıl uygulanır?

OnConnectedAsync ve OnDisconnectedAsync'de bağlantıları izleyin. Kullanıcı-bağlantı eşlemelerini concurrent dictionary veya dağıtılmış önbellekte saklayın. Ölçeklendirilmiş dağıtımlar için Redis gibi paylaşımlı bir depo kullanın. Kullanıcılar bağlandığında veya bağlantıları kesildiğinde ilgili gruplara çevrimiçi durumu güncellemelerini yayınlayın.

S: SignalR backplane'in amacını açıklayın.

Backplane, yük dengelemeli bir ortamda birden fazla sunucu örneği arasında mesajları senkronize eder. Onsuz, sunucu A'dan gönderilen bir mesaj yalnızca sunucu A'ya bağlı istemcilere ulaşır. Redis ve Azure SignalR Service yaygın backplane seçenekleridir. Backplane, tüm sunucuların abone olduğu paylaşımlı bir kanala mesajlar yayınlar.

Performans Optimizasyon Stratejileri

SignalR performansı mesaj boyutu, frekansı ve bağlantı sayısına bağlıdır. ASP.NET Core performans en iyi uygulamaları belgesi detaylı kıyaslamalar sağlar.

  • MessagePack protokolü kullanın — ikili serileştirme, JSON'a kıyasla payload boyutunu %30-50 azaltır
  • Mümkün olduğunda mesajları gruplandırın — birçok küçük mesaj göndermek yerine
  • Grup boyutlarını binlerle sınırlayın — daha büyük kitleler için pub/sub desenlerini değerlendirin
  • Metin ağırlıklı payload'lar için sıkıştırma etkinleştirin
  • Uygun zaman aşımları ayarlayın — eski bağlantılardan kaynakları hızla serbest bırakmak için
csharp
// Daha küçük payload'lar için MessagePack yapılandırması
builder.Services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.SerializerOptions = 
            MessagePackSerializerOptions.Standard
                .WithCompression(MessagePackCompression.Lz4Block);
    });

Sonuç

  • SignalR transport seçimini (WebSockets, SSE, Long Polling) soyutlar ve gerçek zamanlı iletişim için tutarlı bir programlama modeli sağlar
  • Hub'lar bağlantı yönetimini merkezileştirir; güçlü tipli hub'lar istemci metot çağrıları için derleme zamanı güvenliği ekler
  • Gruplar bağlantı alt kümelerine hedefli mesaj dağıtımını etkinleştirir—yeniden bağlantıdan sonra gruplara tekrar katılın
  • Kimlik doğrulama ASP.NET Core identity ile entegre olur; WebSocket bağlantıları için token'ları query string aracılığıyla iletin
  • Sunucu örnekleri arasında mesajları senkronize etmek için Redis backplane veya Azure SignalR Service ile yatay ölçeklendirme yapın
  • Akış, hem sunucudan istemciye hem de istemciden sunucuya senaryolar için IAsyncEnumerable ile artımlı veri dağıtımını destekler

Pratik yapmaya başla!

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

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

Fullstack geliştirici, SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

12 Ağustos 2026 tarihinde güncellendi

Etiketler

#signalr
#asp.net-core
#real-time
#websockets
#dotnet

Paylaş

İlgili makaleler