Redis ile Azure da Mvc, AngularJs ve SignalR İle PubSub Bölüm2
Selamlar,
Bugünkü makalede, bir önceki yazıda bahsedilen Redis ile Azure’da Mvc, AngularJs ve SignalR ile PubSub konularına devam edilmektedir.
Bir önceki makalenin sonunda ilgili kategoriye ait itemların girişi yapmıştır. Şimdi de, girilen itemlar güncellenecektir. Aşağıda görüldüğü gibi seçilen kategoriye ait itemlar listelenmektedir. “item”‘a ait “Düzenle” buttonu tıklandığında “EditItem()” function’ına, ilgili parametreleri ile birlikte gidilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<div ng-show="selectedProduct"> <a ng-href="/AddItem/{{selectedProduct}}">Yeni Bir Ürün Giriniz</a><br /><br /> <div class="panel panel-default pre-scrollable"> <table class="table table-striped table-bordered table-responsive table-condensed table-hover"> <thead> <tr> <th>Id</th> <th>Ad</th> <th>Fiyat</th> <th>Ürün ID</th> </tr> </thead> <tbody> <tr data-ng-repeat="item in Items"> <td> <span>{{item.Id}}</span> </td> <td> <span>{{item.Name}}</span> </td> <td> <span>{{item.Price}}</span> </td> <td> <span>{{item.ProductID}}</span> </td> <td> <button ng-click="EditItem(item.ProductID,item.Id)">Düzenle</button> </td> </tr> </tbody> </table> </div> </div> |
$scope.EditItem(): Aşağıda görüldüğü gibi “EditItem()” action’ına ilgili “ProductID” ve “ItemID” parametreleri gönderilmiştir.
1 2 3 |
$scope.EditItem = function (ProductID, ItemID) { document.location.href = "/EditItem/" + ProductID + "/" + ItemID; } |
Yukarıdaki Action’a ilgili Url’den ulaşabilmek için “Route.Config.cs” dosyasına aşağıdaki path’in eklenmesi gerekmektedir.
1 2 3 4 5 |
routes.MapRoute( name: "EditItem", url: "EditItem/{ProductID}/{Id}", defaults: new { controller = "Home", action = "EditItem", ProductID = UrlParameter.Optional, Id = UrlParameter.Optional } ); |
HomeController.cs/EditItem(): Aşağıda görüldüğü gibi ilgili parametreler “ViewBag” ile ilgili “EditItem” view’ına gönderilmektedir.
1 2 3 4 5 6 7 |
public ActionResult EditItem(int ProductID, int Id) { ViewBag.ProductID = ProductID; ViewBag.Id = Id; return View(); } |
EditItem.cshtml: Aşağıda görüldüğü gibi güncellenecek data bilgileri(“ProductID” ve “ItemID”) “ViewBag”‘ler ile hidden fieldlara yazılmıştır. “Name” ve “Price” alanları “ng-model” directive’i ile “EditItem.Price” ve “EditItem.Name” propertylerine bağlanmışdır. “Kaydet” buttonu tıklanınca, “ng-click” directive’i ile “UpdateItem()” function’ı tetiklenir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@{ Layout = null; } <!DOCTYPE html> <html ng-app="app"> <head> <meta name="viewport" content="width=device-width" /> <title>AddItem</title> <script src="~/Scripts/angular.min.js"></script> <script src="~/Scripts/EditItem.js"></script> </head> <body> <div ng-controller="EditItemController"> <p><b>Ürün Adı:</b></p> <input type="text" ng-model="EditedItem.Name" id="Name" /><br /> <p><b>Fiyat(TL):</b></p> <input type="text" ng-model="EditedItem.Price" id="Price" /> <input type="button" ng-click="UpdateItem()" value="Kaydet" /> <input type="hidden" value="@ViewBag.ProductID" id="hdnProductID" /> <input type="hidden" value="@ViewBag.Id" id="hdnItemID" /> </div> </body> </html> |
EditItem.js: Aşağıda görüldüğü gibi sayfa ilk yüklendiği zaman “GetEditItem()” action’ına post işlemi yapılmakta ve hidden alanlara yazılan “Id” ve “ProductID” ilgili action’a parametre olarak post edilmektedir. Dönen result(düzenlenecek item’ın kendisi) AngularJS’deki “$scope.EditItem” property’sine atanmaktadır. “$scope.Update()” function’ında güncellenen item’ın “Price”,”Name”,”ProductID” ve “Id” alanları yaratılan item sınıfı içinde “UpdateItem()” action’ına gönderilmekte ve işlemin tamamlanması ardından ana sayfaya dönülmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var app = angular.module("app", []); app.controller('EditItemController', function ($scope, $http) { $http({ method: 'POST', url: '/Home/GetEditItem', data: { 'ProductID': document.getElementById("hdnProductID").value, 'Id': document.getElementById("hdnItemID").value } }).success(function (result) { console.log("Edit Item: "+JSON.stringify(result)); $scope.EditedItem = result; }); $scope.UpdateItem = function () { var item = { "Name": $scope.EditedItem.Name, "Price": $scope.EditedItem.Price, "ProductID": document.getElementById("hdnProductID").value, "Id": document.getElementById("hdnItemID").value, }; $http({ method: 'POST', url: '/Home/UpdateItem', data: item }).success(function () { document.location.href = "/"; }); } }); |
HomeController.cs/GetEditItem(): Aşağıda görüldüğü gibi “Edit” sayfasına gelinince, önce “IRedisTypeClient”‘a bağlanılmış daha sonra da ilgili ProductID’ye göre itemlar “itemClient.Lists[]” ile çekilmiştir. Son olarak düzenlenecek item, linq ile bulunup Json olarak dönülmüştür.
1 2 3 4 5 6 7 8 9 10 11 |
public JsonResult GetEditItem(int ProductID, int Id) { var conf = new RedisEndpoint() { Host = "xxxxxxx.redis.cache.windows.net", Password = "yyyyyyyyyyyyyyyy", Ssl = true, Port = 6380 }; using (IRedisClient client = new RedisClient(conf)) { var itemClient = client.As<Item>(); var itemList = itemClient.Lists["urn:item:" + ProductID]; var toUpdateItem = itemList.First(x => x.Id == Id); return Json(toUpdateItem, JsonRequestBehavior.AllowGet); } } |
C# tarafındaki kodların Redis karşılığ yukarıdaki gibidir:
- “LLEN” “urn:item:3” : Liste’nin toplam eleman sayısını verir.
- “LRANGE” “urn:item:3” “0” “-1”: Liste içindeki elemanların başlangıç ve bitiş indexleri verilerek toplu olarak listelemesini sağlanır. Burada “-1” sonuna kadar yani tümü anlamına gelmektedir.
HomeController.cs/UpdateItem(): Aşağıda, güncellenecek itemin bilgileri girildikten sonra kaydet buttonuna basılınca post edilen “UpdateItem()” methodu gözükmektedir. Öncelikle item’ın bulunduğu ürün gurubuna göre tüm elemanlar çekilir. Bu bir listeye aktarılır. List içindeki ilgili itemlar arasından “Linq” extension kullanılarak güncellenecek item’in index numarası bulunur. Aslında burada liste içindeki tüm itemlar gezilmiş ve “id” numarasına göre tek tek bakılarak güncellenecek item’ın index’i aranmıştır. “id” değerine göre linq ile çekilen bu item, önce güncellenmiş daha sonra bulunduğu index’e ilgili liste’den çıkarılmışdır. Son olarak fiyata göre güncellenen bu item, Liste’ye tekrar ait olduğu sıraya göre konmuştur.
Not: Görüldüğü gibi Redis’de List yapıları güncellemeye pek te uygun yapılar değildir. Çünkü ilgili item’ı key’e göre değil index numarasına göre bulmak gerekmekte ve bunun için belkide tüm liste dönülmektedir. Bu tür durumlarda “Hashes” gibi yapılar ile çalşmak daha doğru sonuclar doğurabilir. Siz de bu konuda fikirlerinizi paylaşırsanız sevinirim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public void UpdateItem(Item item) { var conf = new RedisEndpoint() { Host = "xxxxxxx.redis.cache.windows.net", Password = "yyyyyyyyyyy", Ssl = true, Port = 6380 }; using (IRedisClient client = new RedisClient(conf)) { IRedisTypedClient<Item> itemClient = client.As<Item>(); IRedisList<Item> itemList = itemClient.Lists["urn:item:" + item.ProductID]; var index = itemList.Select((Value, Index) => new { Value, Index }) .Single(p => p.Value.Id == item.Id).Index; var toUpdateItem = itemList.First(x => x.Id == item.Id); toUpdateItem.Name = item.Name; toUpdateItem.Price = item.Price; itemList.RemoveAt(index); if (itemList.Count - 1 < index) itemList.Add(toUpdateItem); else itemList.Insert(index, toUpdateItem); } } |
Yukarıda ServisStack ile yapılan işlemlerin redis tarafındaki komut karşılıkları aşağıdaki gibidir.
“LSET” “urn:item:3” “0”: Listenin belirlenen indexdeki elemanına değer atanır.
“LREM” “urn:item:3” “0”: Listeden belirlenen sayı kadar eleman çıkarılması sağlanır. Çıkarılacak sayı pozitif ise baştan sona, negatif ise sondan başa doğru belirtilen sayı kadar eleman çıkarılır. “ServiceStack” tarafında karşılığı “itemList.RemoveAt()”‘dir.
“RPUSH” “urn:item:3” : Belirlenen key ile Listeye eleman eklenmesi sağlanır. “ServiceStack” tarafında karşılığı “itemList.Add()”‘dir.
Seçilne Product’a göre ürünün güncellenmesi on the fly olarak Redis’de rem memoryde yapılmaktadır.
Şimdi sıra geldi en ucuz 5 ürünü kayar band olarak ekranın altında listelemeye. Bunun için öncelikle yeni bir ürün giriş olduğunda, bu ürünü “SortedSet” dediğimiz sıralı bir diziye de koyalım. Böylece fiyat bilgisine göre sıral ürünler içinden ilk 5’i alınarak en ucuz 5 ürüne ulaşılır.
SaveItem(): Yeni bir ürün girişi olduğunda “urn:Rank” keyword’ü ile SıralıSet’e ilgili item “Name” ve “Price” alanları ile atılır.
1 2 3 4 5 6 |
public void SaveItem(Item item) { . . client.AddItemToSortedSet("urn:Rank", item.Name, item.Price); } |
Yukarıdaki durumun Redis’deki karşılığı aşağıdaki gibidir:
“ZADD” “urn:Rank” “100”: SortedList’e yeni girişi yapılan ürün fiyatı ile birlikte eklenir. (AddItemToSortedSet()).
Aynı şekilde var olan bir ürünün güncellenmesinden sonra “urn:Rank” keyword’unden güncellenen item çıkarılır ve tekrar eklenir. Burada amaç ilgili “Price”‘a göre güncellenen item’ın tekrardan “SortedSet”‘e ait olduğu sıraya göre konmasıdır. Böylece son güncel sıra “SortedList”‘de de korunmuş olunur.
1 2 3 4 5 6 |
public void UpdateItem(Item item) { . . client.RemoveItemFromSortedSet("urn:Rank", item.Name); client.AddItemToSortedSet("urn:Rank", item.Name, item.Price); } |
Yukarıdaki durumun Redis’deki karşılığı aşağıdaki gibidir:
“ZREM” “urn:Rank” : Sıralı listeden belirlenen key’e göre ilgili item çıkarılır. (RemoveItemFromSortedSet())
“ZADD” “urn:Rank” : Sıralı listeye fiyatı değişen ürün adı ve fiyatı ile birlikte tekrar eklenir.(AddItemToSortedSet)
Şimdi sıra geldi Index.cshtml sayfa ilk yüklenirken ilgili Rank List’in AngularJS tarafından doldurulmasına:
index.js: Aşağıda görüldüğü gibi “$scope.Ranks” propertysi “GetRanks()” methodu ile aşağıdaki gibi doldurulur.
1 2 3 4 5 6 7 |
$http({ method: 'GET', url: '/Home/GetRanks' }).success(function (result) { console.log("RankList: "+JSON.stringify(result)); $scope.Ranks = result; }); |
HomeController.cs/GetRanks(): Redis’e bağlanıldıktan sonra aşağıda görüldüğü gibi sıralı listeden ilk 4 item “GetRangeWithScoresFromSortedSet()” methodu ile çekilir. Daha sonra ilgili list, item listesinde gezilerek “Id=counter” şekilinde bir identity değeri de eklenerek atanır. Sonra ilgili “RankList“, Json olarak geri dönülür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public JsonResult GetRanks() { var conf = new RedisEndpoint() { Host = "xxxxx.redis.cache.windows.net", Password = "yyyyyyyyy", Ssl = true, Port = 6380 }; using (IRedisClient client = new RedisClient(conf)) { IDictionary<string, double> Data = client.GetRangeWithScoresFromSortedSet("urn:Rank",0,4); List<Item> RankList = new List<Item>(); int counter = 0; foreach(var item in Data) { counter++; RankList.Add(new Item() { Name = item.Key, Price = (int)item.Value, Id=counter }); } return Json(RankList, JsonRequestBehavior.AllowGet); } } |
Index.cshtml: İlgili en ucuz 5 ürün aşağıda görüldüğü gibi, AngularJS ile “Ranks” içinde gezilerek ekrana basılır.
1 2 3 4 5 6 7 8 9 10 11 12 |
<div id="rank"> <font color="WHITE"> <marquee direction="left" style="background:RED" scrollamount="20"> <h2> Top 5: <span ng-repeat="item in Ranks"> {{item.Id}}-){{item.Name}} : {{item.Price}}TL </span> </h2> </marquee> </font> </div> |
Şimdi sıra geldi makalenin en can alıcı ve önemli kısmına. Değişen bu “SortedList” datalarının, tüm clientlar’a real time olarak bildirilmesine. Bu işlemin redis karşılığı “Pub/Sub” olarak bilinen [Publisher / Subscriber]’dır. Yani herhangi bir ürün girişinin ya da güncellemesinin olması durumunda, yeni oluşan en ucuz son 5 ürün sıralı listesi o anki tüm clientlara real time olarak bildirilmelidir. Bu aslında Observer Design Pattern ‘dan başka birşey değildir.
Image Source: https://www.abaptutorial.com/wp-content/uploads/2011/06/abap-observer-design-pattern.png
Öncelikle yeni bir ürün girişi olduğu zaman, oluşan yeni “SortedList“‘i tüm clientlar ile paylaşalım. Projeye “JsonConvert” dönüşümü için aşağıdaki “Newtonsoft.Json” package’ı indirilir.
HomeController.cs/SaveItem(): Methodunun sonuna aşağıdaki kodlar eklenir. Burada amaç, yeni bir ürün girişi olduğu zaman var olan SortedList yeniden oluşturulur. Böylece “GetRangeWithScoresFromSortedSet()” ile en ucuz ilk 5 ürün alınmış olunur. Daha sonra “RankList” adında bir “List<Item>“‘a doldurulur. İlgili “RankList“, json formatına Newtonsoft kütüpahanesi kullanılarak “JsonConvert.SerializeObject()” methodu ile çevrilir. Son olarak json formatına çevirilen “itemJson“, “client.PublishMessage()” komutu ile “Rank” subscriber’ına gönderilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//Publis top 5 Ranked Items IDictionary<string, double> Data = client.GetRangeWithScoresFromSortedSet("urn:Rank", 0, 4); List<Item> RankList = new List<Item>(); int counter = 0; foreach (var itm in Data) { counter++; RankList.Add(new Item() { Name = itm.Key, Price = (int)itm.Value, Id = counter }); } var itemJson = JsonConvert.SerializeObject(RankList); client.PublishMessage("Rank", itemJson); //--------------------------------------------- |
Yukarıdaki kodların Redis tarafındaki karşılığı aşağıdaki gibidir:
“ZRANGE” “urn:Rank” “0” “4” “WITHSCORES”: Sıralı listeden yani SortedList’den ilk 5 tanesi value değerleri ile birlikte çekilir.(GetRangeWithScoresFromSortedSet()).
“PUBLISH” “Rank” : “Rank” Subscriber’ına Json olarak çevrilen tüm “RankList” gönderilir.(PublishMessage()).
HomeController.cs/UpdateItem(): Methodunun sonuna aşağıdaki kodlar eklenir. Var olan bir ürün güncellendiğinde, “SortedList” değiştiği için önce ilk 5 kayıt çekilir, daha sonra aynı yeni ürün girişinde olduğu gibi, “RankList“‘e konur ve json formatına çevrilip “Rank” subscriber’ına gönderilir.
1 2 3 4 5 6 7 8 9 10 11 12 |
//Publis top 5 Ranked Items IDictionary<string, double> Data = client.GetRangeWithScoresFromSortedSet("urn:Rank", 0, 4); List<Item> RankList = new List<Item>(); int counter = 0; foreach (var itm in Data) { counter++; RankList.Add(new Item() { Name = itm.Key, Price = (int)itm.Value, Id = counter }); } var itemJson = JsonConvert.SerializeObject(RankList); client.PublishMessage("Rank", itemJson); |
Şimdi sıra geldi, bu gönderilen mesajı karşılıyan “Rank” Subscriber’ını. Bu işlem için yeni bir consol application yapıcağız. Aslında herbir yeni “Subscriber” için farklı bir console application yapılabilir.
Ve böylece yoğun olabilecek bir iş topluluğunu, parça parça mikroservices olarak adlandırabileceğimiz yapılar ile kolaylıkla bölebilir; ilgili mikroservices üzerinde bir takım değişiklikler yaparak bir docker içine koyup scale edip performansı çok daha fazla arttırabiliriz.
Rank/Program.cs(Console Application): Aşağıda görüldüğü gibi “CreateSubscription()” methodu ile “sub” adında bir subscription oluşturulmuştur. “OnMessage()” methodunda publisher dinlenerek, herhangi bir mesaj geldiğinde şu an için ilgili mesaj“Newtonsoft” kütüpahanesi kullanılarak “json” formatına çevrilip bir item liste atanmıştır. Yaratılmış olan subscribe’ın ait olmuş olduğu channel “SubscribeToChannels()” methodu ile “Rank“‘e atanmıştır. Listeye atılan “item” modeli aşağıda görüldüğü gibi “item” sınıfı ile tanımlamıştır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
using Newtonsoft.Json; using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Rank { class Program { static void Main(string[] args) { var conf = new RedisEndpoint() { Host = "xxxxxx.redis.cache.windows.net", Password = "yyyyyyyyy", Ssl = true, Port = 6380 }; using (IRedisClient client = new RedisClient(conf)) { IRedisSubscription sub = null; using (sub = client.CreateSubscription()) { sub.OnMessage += (channel, message) => { try { List<Item> items = JsonConvert.DeserializeObject<List<Item>>(message); Console.WriteLine((string)message); } catch (Exception ex) { Console.WriteLine(ex.Message); } }; } sub.SubscribeToChannels(new string[] { "Rank" }); } Console.ReadLine(); } } public class Item { public long Id { get; set; } public string Name { get; set; } public int Price { get; set; } public int ProductID { get; set; } } } |
Şimdi sıra geldi Console Application’da alınan bu mesajları”SignalR” kullanarak o anki clientlara göndermeye. Öncelikle aşağıdaki SignalR paketleri Nuget’den indirilir.
Öncelikle “Rank” adında signalR “Hub” sınıfı oluşturup, oluşan yeni “Rank List” tüm clientlara real time olarak “getRank()” function’ı ile gönderilir.
1-)HomeController.cs/Rank:
1 2 3 4 5 6 7 |
public class Rank : Hub { public async Task SendRank(List<Item> rankList) { await Clients.All.getRank(rankList); } } |
2-) Index.js: Aşağıda görüldüğü gibi ilgili “Rank” signalR class’ına “$.connection.rank” ile bağlanmıştır. Ve daha sonra ilgili hub başlatılmıştır.”hub.start()“. “getRank()” function’ı kendisine gelen “rankList“‘i “$scope.Ranks”‘e atayıp “$scope.$apply()” ile bind etmiştir. Böylece sayfanın sonundaki kayan bandın real time olarak tüm clientlar için değişmesi sağlanmıştır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="/signalr/hubs"></script> var hubproxy = $.connection.rank; $.connection.hub.logging = true; $.connection.hub.start(function () { console.log("hub.start.done"); }); hubproxy.client.getRank = function (rankList) { $scope.Ranks = rankList; $scope.$apply() console.log("client.getRank.done"); console.log(JSON.stringify(rankList)); } //------------------------------------------------- |
3-) Rank/Program.cs: Öncelikle aşağıda görüldüğü gibi, herhangi bir ürün girişinden veya güncellenmesinden sonra “Redis”‘in “Publisher” özelliği ile [“client.PublishMessage(“Rank”, itemJson);“] değişen SortedList önceden yazılan Micro Servis olarak tabir ettiğimiz “Program.cs ConsoleApplication”‘daki “Rank Subscribe”‘ına gönderilir. “OnMessage()” methodunda, yakalanan message yani “RankeList”, yazılmış olan “SignalRClass”‘ındaki “SendRank()” asenkron methodunu call eder. İlgili method, “http://localhost:34511/”‘da tanımlı “Rank” signalR sınıfına bağlanıp tüm clinetlara güncel son sıralı listeyi göndermek için “SendRank()” methodunu tetikler.
Böylece değişen ve yeni girilen tüm data, asenkron olarak başka bir microservices(Consol Application) tarafından Redis’in “pub/sub” özelliği kullanılarak Json formatında yakalanması; yakalanan sortedListin, SignalR teknolojisi kullanılarak tüm clientlara real time olarak gönderilmesi, ve en sonunda Clientlara gelen datanın, AngularJs modeli doldurularak ekrana real time olarak basılması sağlanmıştır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
using Microsoft.AspNet.SignalR.Client; using Microsoft.AspNet.SignalR.Client.Transports; using Newtonsoft.Json; using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Rank { class Program { static void Main(string[] args) { var conf = new RedisEndpoint() { Host = "xxxxxxx.redis.cache.windows.net", Password = "yyyyyyyyyyyyyyyy", Ssl = true, Port = 6380 }; using (IRedisClient client = new RedisClient(conf)) { IRedisSubscription sub = null; using (sub = client.CreateSubscription()) { sub.OnMessage += (channel, message) => { try { List<Item> items = JsonConvert.DeserializeObject<List<Item>>(message); Console.WriteLine((string)message); SignalRClass sc = new SignalRClass(); sc.SendRank(items); } catch (Exception ex) { Console.WriteLine(ex.Message); } }; } sub.SubscribeToChannels(new string[] { "Rank" }); } Console.ReadLine(); } } public class SignalRClass { public async Task SendRank(List<Item> rankList) { HubConnection hubConnection = new HubConnection("http://localhost:34511/"); IHubProxy hubProxy = hubConnection.CreateHubProxy("Rank"); await hubConnection.Start(new LongPollingTransport()); hubProxy.Invoke("SendRank", rankList); } } public class Item { public long Id { get; set; } public string Name { get; set; } public int Price { get; set; } public int ProductID { get; set; } } } |
Yukarıda görüldüğü gibi 4 farklı teknoloji Mvc, AngularJS, Azure üzerinde Redis ve SignalR birlikte çok uyumlu bir şekilde çalışmaktadır. Azure üzerinde oluşturulan NoSql memcached Redis, kayıtları çok hızlı bir şekilde yazmakta ve okumaktadır. Böylece girilen data işlemlerinde (güncelleme, listeleme ve sıralama gibi), Redis kullanmaktadır. İlgili dataların ekrana basılması işi AngularJs’e aittir. Böylece modellerde olan değişikliklerin, “UI” tarafında ayrıca kod yazılmadan gösterilmesi sağlanmıştır. Yine Redis’in “Pub/Sub” özelliği ile değişen veya yeni girilen tüm datalar, kendi içinde socket teknolojisi kullanılarak farklı bir Consol Application’a gönderilmiştir. Burada amaç, performans ve uygulamadan bağımsız arkadan çalışan bir yapı oluşturmaktır. Ayrıca herbir tablo için farklı bir consol application ya da diğer bir düşünce ile mikroservices yaratılarak performans iyice arttırılabilir. Hatta bu mikroservices ler docker yapısına uygun bir hale getirilerek, docker içine konup Azure ortamında scale yapılarak büyük trafikler için performanslı yapılar haline getirilebilir. Daha da ileri gidersek, bu Console Applicationlarda, gelen tüm Json Data database ya da loglama amaçlı DocumentDB’ye de yazılabilir.
Görüldüğü gibi hayal etmenin sonu ve sınırı yoktur. Kodları iyileştirmenin, bir adım daha ileriye götürmenin tek yolu, araştırmak ve yenilikleri takip etmekten başka birşey değildir. Yeni bir makalede görüşmek üzere hoşçakalın.
Source Code: https://github.com/borakasmer/RedisPubSubWithSignalR
Source:
Hocam 2. bolum dediginiz kadar varmis elinize saglik.
Fakat redis agirlikli daha enterprise uygulamalar bekliyoruz :)
Saygilar,
Teşekkürler Yiğit;
Önceden planladığım birkaç konu daha var. Onlardan sonra redis’i daha farklı projeler ile irdelemeye devam edebiliriz.
Hocam merhabalar, redis ile anlattığınız gibi azuredan değil de uzakmasaüstü bağlantısından -tarih/saat vb.- veri çekmemiz mümkün müdür ?
Selam Mehmet,
Redis ile Azure yerine remote bir makinadan data çekmen tabiki mümkün…
Kolay gelsin…
Merhaba,
Nuget package manager üzerinde iki farklı redis package’i mevcut: StackExchange ve ServiceStack.
Sizin ServiceStack seçmenizde özel bir neden var mı?
Evet var. StackExchange daha çok Azure gibi Cloude üzerinden redis kullanılıyor ise tercih edilen bir Library diyebiliriz.
Ben daha çok model yapısı üzerinde çalıştığım için uygulama cloude’da çalışmasına rağmen ServisStack kütüpahanesini kullandım. Türkiyede iş hayatında da genelde ServisStack kullanılır. Hatta ben hiç StackExchange kullanan bir yapı ile karşılaşmadım:)
İyi çalışmalar.