SignalR ile Canlı Kullanıcı Sayısını Bulma ve Redis ile Loglama Bölüm 2

Selamlar,

Bugün bir önceki makalede bahsettiğimiz console application’ı yazıp, Redis Pub/Sub özelliği ile log bilgisini MsSql bir server’a yazacağız. Ayrıca toplam kullanıcı  sayısını ve her bir server’a göre kırılımının gösterildiği bir sayfayı, performansı da göz önüne alarak oluşturacağız.

Öncelikle “UserCount” tablosu aşağıdaki gibi oluşturulur: Bu tabloda server bazından gelen kullanıcı sayısı tutulacaktır.

Table

Şimdi sıra geldi Redis’den Pub/Sub ile dataların publish edildiği “UserCountService“‘i yazmaya. Bunun için “RedisSqlService” adında bir console application oluşturulur.

Program.cs: Öncelikle RedisEndPoint oluşturulur. RedisClient‘a connect işlemi yapıldıktan sonra “CreateSubscription()” methodu ile 6379 portdan ilgili method dinlenmeye başlanır. Mesaj geldiği zaman yani “sub.OnMessage” durumunda gelen “message” split ile “æ” işaretine göre ayrılıp server ismi ve kullanıcı sayıları bilgileri ayrıştırılır.

Projeye “UserCountContext” adında CodeFirst nesnesi eklenir. İlgili tablo olarak”UserCount” tanımlanır. Daha sonra aşağıda görüldüğü gibi “SaveData()” methodu oluşturulur. Gelen server ismi ve kullanıcı sayısı bu oluşturulan tabloya yazılır. Burada dikkat edilecek nokta “async” olan method,  static Main() methodu tarafında çağrılırken sonuna Wait() methodu eklenerek var olan Main() methodunun genel yapısı asenkron olarak değiştirilmemiştir. Zaten denenirse de hata alınılması kaçınılmazdır:) Böylece gelen tüm data yani server adı, anlık toplam kullanıcı sayısı ve kaydedilen tarih ve saat bilgisi MsSql serverda “UserLog” database’ine kaydedilmiş olunur.

Main() methodunun sonuna dinlenecek Redis kanalının “UserCountService” olacağı “SubscribeToChannels()” methodu ile tanımlanmaktadır.

Uygulama çalıştırılıp loglama işlemine başlanınca, aşağıdaki gibi bir kayıt kümesi ilgili tabloda saklanır.

SqlResult

Aşağıda DB katmanın, CodeFirst tarafında karşılığı olan poco sınıflarının tanımı yapılmıştır.

UserCount.cs

UserCountContext.cd:

  1. http://localhost:3453/
  2. http://localhost:78/

Şimdi sıra geldi farklı serverlara ait kullanıcı sayılarının toplamını göstermeye. Bunun için öncelikle farklı bir sunucudan Index.cshtml sayfayı yayınlanması gerekmektedir. Bu örnekte proje bir de IIS serverdan “http://localhost:78/” portundan yayımlanmıştır. Böylece elde bir IIS Express’den bir de IIS’den yayımlanmış 2 farklı sunucu olmuştur. Artık farklı yerlerden yayımlanan Index.cshtml sayfasına gelen anlık kullanıcı sayısı ölçülebilir.

Global.cshtml:

Global

Şimdi sıra geldi en önemli kısma, 2 farklı sunucudaki toplam kullanıcı sayısını almaya : Burada performans konusu çok önemlidir. Örneğin Redis veya Azure üzerinde Scale yapılabilir. (Birden fazla sunucu üzerine signalR tek bir sunucu gibi yayımlanabilir.) Tüm sunucular bu signalR sınıfına bağlanıp toplam kullanıcı sayısını tutulabilir.  Ben burada daha basit ve pratik bir yol kullandım. Tüm sunuculardaki “Admin.cshtml” sayfaları “Global.cshtml” bir sayfa altında IFrame olarak yukarıda görüldüğü gibi koydum.

Global.cshtml: Aşağıda görüldüğü gibi farklı kaynaklardan yayımlanan “Admin” sayfaları “IFrame” olarak “Global” sayfasına eklenmiştir. Bir de toplam kullanıcı sayısının yazılacağı “message” id’li bir span oluşturulmuştur.

Eğer önceki makalem olam IFrame’de Cross Domain‘i okursanız bundan sonra anlatılacak konuyu daha iyi anlayabilirsiniz. Yapılması gereken IFrameler içerisinde kullanıcı sayısı değiştiğinde, parent yani Global.cshtml sayfadaki bir function’ın, IFrame’den gönderilen server ismi ve kullanıcı sayısı ile tetiklenmesi ve böylece ana sayfadaki Toplam Kullanıcı sayısının değişmesinin sağlanmasıdır. Buradaki zorluk tabiki cross domain problemidir. Bunu aşmanın yolu, IFrameler içinde “parent.postMessage()” ile parent yani Global.cshtml sayfaya ilgili dataların gönderilmesi ve Parent yani Global.cshtm tarafında da “addEventListener()” ya da browser desteğine göre “attachEvent()” methodları ile IFrame’den gelen datanın dinlenmesinin sağlanmasıdır.

post

Admin.cshtm: Kodlar aşağıdaki gibi değiştirilir. Önceki makaleden hatırlayacağınız gibi Client, “Index.cshtml” sayfaya gelince ya da ayrılınca, Admin sayfasındaki “refreshUserCount()” function’ı tetiklenmekte idi. Değişen UserCount servername’e göre ilgili tablonun içine basılır. Bundan sonra ilgili datalar “parent.postMessage(data, “http://localhost:3453”)” methodu ile Parent’a gönderilir. İlk parametre gönderilen server adı ve kullanıcı sayısı bilgileridir. 2. parametre ise Parent yani Global.cshtml sayfanın bulunduğu sunucu adresidir.

W2g09

cross-domain-iframe-resize

Global.cshtml: İlgili kodlar aşağıdaki gibi değiştirilmiştir. Bu örnekte 2 sunucudan gelecek kullanıcı sayılarına bakılmaktadır. “addEventListener(“message”, listener, false)” methodu ile IFrame’den gelen mesajlar dinlenip “listenar()” function’ı tetiklenmiştir. İlgili function’da datanın geldiği sayfanın url’i “evet.origin” ile kontrol edilmekte ve dışarıdan gelebilecek ataklar bu şekilde bir nebzede olsa önlenebilmektedir. Gelen data parse edilip, server adı ve kullanıcı sayıları bilgileri alındıktan sonra ilgili toplan kullanıcı sayısı yeniden bulunup ekrana basılır.

Bu makalede farklı serverlardaki anık kullanıcı sayısını real time olarak signalR web socket ile saydık. Redis Cache kullanarak timeout zamanında, pub/sub özelliği ile console bir application’a server ismi ve kullanıcı sayısını gönderdik. Daha sonra bu data’yi MsSql bir DB’ye asenkron olarak kaydettik. Ayrıca bir monitor sayfası yaptık. Ve diğer admin sayfaları bu sayfaya IFrame olarak koyduk. Daha sonra “parent.post()” ve “windows.addEventListener()” functionları ile toplam kullancısı sayısını tek bir “Global” sayfasında göstermeyi başardık.

Böylece geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hoşçakalın.

Herkes Görsün:

Bunlar da hoşunuza gidebilir...