Server-side tarafında geliştirme yapan arkadaşlar bilirler ki request-response time ları çok büyük önem sarf etmektedir. Örnek olarak, bir muhasebe DB niz var ve her gün gece 23:59 da günlük raporlar giriliyor veya 3 dkka yeni kayıt girilen bir yapıda olabilir. İlgili tabloda şuana kadar 200 bin kayıt girilmiş diyelim. select * from Raporlar dediniz ve size 200 bin kayıtı ortalama 15 sn de getirdi (DB nin serve edildiği Pc nin özellikleri ve network hızı gibi çeşitli etkenlere göre değişir). Aslında bu gibi yapılarda ilgili StoraProcedure e paging parametreleri vererek daha performanslı ve hızlı bir sorgu yazabiliriz ancak bu durum için bile Cache yapısını uygulamamıza entegre edebiliriz. Şimdi bu raporları feed eden bir mobil uygulamamız, Web Sayfanız veya bir masaüstü uygulamanız olabilir ve iş ilgili uygulamanın kullanım oranına göre dakikada 100-200 request te bulunuyor olabilirsiniz. Bu uygulamalara db ile connection'ı sağlayan bir Web Api uygulamamız olsun. Şimdi yukarıda ki case de uygulamada bulunan RaporlarController 'ına dakikada 100-200 arası istek bulunmakta. Ne yapacağız peki sürekli olarak DB ye git select * from Raporlar deyip 200 bin kayıtı almak için 15 sn sürsün network vs işlemlerinden dolayı 2 sn de ordan olsun artı birde kullanıcının internet hızı kotalımı dersin :) ttnet sağolsun hızı düşürmüş 2 mb'e ve oda yaklaşık olarak 5 sn sürsün diyelim (değerler tamamiyle dummy dir). Şimdi küçük bir matematik işlemiyle ortalama kaç sn de veriyi getiriyoruz;
DB QueryResult : 15 sn
WebApi projesinin Download Süresi : 2 sn
Client uygulamasının Download Süresi : 5 sn
Client uygulamasının bu veriyi ekrana çizmeside yaklaşık 2 sn diyelim (Performanslı cihazlarda)
int[] arr = { 15 , 2, 5, 2 };
int sumResult = arr.Sum();
Console.WriteLine(sumResult);
24 saniye
Adama "Oh My God" dediğinde "Yes your god" diye cevap verirler.
Tamı tamına 24 saniye (biraz abartmışta olabiliriz ). Günde ortalama 100 kişinin kullandığını düşündüğümüzde her gelen 24 sn beklicek. Böyle bir projeyi al çöpe at derler adama. Benzer bir olay daha önce çalıştığım bir şirkette başıma geldi ve page_load da db ye gidip 4.600.000 kayıt için sorgu atılıyordu ve bazı işlemler yapılmaya çalışılıyordu. Projeyi bana assign edip müşteri sayfayı açamıyormuş bi bakarmısın dediler ve sorunu anladığımda yazılımdan soğmuştum diyebilirim.
Her neyse gelelim konumuza. Projeyi bu halde bırakmayalım ama çöpede atmayalım. Projemize sağ tıklayıp nugetten WebApi OutPutCache.Core ve OutPutCache.v2 dll lerini ekleyelim.
Senaryomuz şu şekilde olacak;
1-Controller bazında hem server side için hemde client için iki tarafta da cache sağlayacak bir yapı yapıyoruz. Kullanacağımız kütüphaneye 2 parametre vericez ServerTimeSpan ve ClientTimeSpan . Biri ServerSide için cache'i sağlicak yani kendine gelen ilk request'in response'ını alıp set edilen süre boyunca aynı requestle başka bir kullanıcı geldiğinde cache den alıp o yeni gelen kullanıcıya verecek. Diğeri ise ClientSide için clienta dönen response'un header'ına Cache-Control →max-age=60 eklicek. Bu şu anlama geliyor; Client'a diyor ki arkadaş ben bu respons'u 60 sn cache ledim ve sende istersen gelen response'u biyerde tutup bana 60 sn boyunca gelmeyebilirsin. 60 sn sonra tekrardan gel. Şimdi gelelim code tarafına ilk olarak WebApiCacheAttribute adında CacheOutputAttribute inherıt olan bir attribute tanımlıyoruz. Alında direkt olarak CacheOutputAttribute controllerımızın içerisindeki metodların başına ekleyebilirdik ancak yönetimi daha kolay olur düşüncesiyle araya işimi daha kolaylaştıran WebApiCacheAttribute adında CustomAttribute ünü yazdım.
public class WebApiCacheAttribute : CacheOutputAttribute
{
public ApiCacheAttribute()
: this(WebConfigApiClientCacheDuration,WEebConfigApiServerCacheDuration){ }
public ApiCacheAttribute(int clientCacheDuration = 0,
int serverCacheDuration = 0)
{
base.ServerTimeSpan = serverCacheDuration;
base.ClientTimeSpan = clientCacheDuration;
}
}
Üstte görüldüğü gibi bu Cache attribute'ü 2 parametre alıyor. Bu parametreleri attribute implementasyon sırasında aşağıda olduğu gibi biz değer atamaz isek WebConfig dosyasında tanımlı olan değerli alarak Cache sürelerini set ediyor.
WebConfig de appsettings de kayıtlı olan değerleri okuyarak cache işlemini yapar
[WebApiCacheAttribute]
public IHttpActionResult GetItems()
{
var products= new IkiYuzBinKayit(); //db den 200 bin kayit getirmişiz varsayalım
return Ok(product);
}
Ama istersek aşağıda olduğu gibi bizde bu değerleri set edebiliriz
[WebApiCacheAttribute(ApiServerCacheDuration=120,ClientCacheDuration=120)]
public IHttpActionResult GetItems()
{
var products= new IkiYuzBinKayit(); //db den 200 bin kayit getirmişiz varsayalım
return Ok(product);
}
Sonuç olarak web api projemizde cache attribute eklediğimiz metoda yapılan sorgular set edilen sürelere göre cache lenir ve o süre boyunca aynı parametrelerle gelen bütün kullanıcılara cachelenmiş olan response döner. Süreç server cache süresi bittiğinde sonlanır ve yeniden gelecek olan ilk sorgu beklenir ve döngü şeklinde devam eder.
Not ! Cache Cache'dir ancak hangi datanın cachelenip cachelenmemesi konusu çok ama çok önemlidir !! İyice düşünüp karar verilmesi gereken bir konudur.