https://www.buraksenyurt.com/Burak Selim Şenyurt - Asp.Net 4.0 Beta 22016-08-08T07:27:38+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/TFI-109-IIS-Uzerindeki-Uygulamalarc4b1-Kod-Yoluyla-OgrenmekTFİ 109 - IIS Üzerindeki Uygulamaları Kod Yoluyla Öğrenmek2014-08-27T13:52:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p>Diyelim ki sunucudaki <strong>IIS </strong>üzerinde konuşlandırdığınız Web uygulamalarının bir listesini almak istiyorsunuz. Bunun elbette pek çok yolu olduğunu biliyorsunuz. Bir Powershell script' i belki de işinizi görür. Ancak belki de siz bunu kendi geliştireceğiniz windows forms uygulamasında bu listeyi kullanmak istiyorsunuz. Ne yaparsınız? Kod yardımıyla <strong>IIS </strong>üzerindeki <strong>Application</strong>' ları, <strong>Site</strong>' ları öğrenebilir misiniz?</p>
<p>Aslında hep elinizin altında olan<em> (Windows\System32\inetsrv\Microsoft.Web.Administration.dll)</em> ve hatta isterseniz <strong>NuGet Package Manager </strong>ile de indirebileceğiniz <strong>Microsoft.Web.Administration</strong> kütüphanesini kullanarak bu işi gerçekleştirmeniz oldukça kolay. Nasıl mı? İşte böyle.</p>
<p><img src="http://www.buraksenyurt.com/pics/2014%2f8%2ftfi109.png" alt="" /></p>
<p>Başka neler mi yapabilirsiniz? Örneğin bir Application Pool' u Recylce edebilirsiniz. Ya da bir Web Site' ı Stop-Start. Hatta yeni bir Web Site bile açabilirsiniz. Araştırmaya değer değil mi?</p>
<p>Başka bir ipucunda görüşmek dileğiyle.</p>2014-08-27T13:52:00+00:00bsenyurthttps://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=b0a0f719-7be3-43f8-96a5-6635b286bc471https://www.buraksenyurt.com/trackback.axd?id=b0a0f719-7be3-43f8-96a5-6635b286bc47https://www.buraksenyurt.com/post/TFI-109-IIS-Uzerindeki-Uygulamalarc4b1-Kod-Yoluyla-Ogrenmek#commenthttps://www.buraksenyurt.com/syndication.axd?post=b0a0f719-7be3-43f8-96a5-6635b286bc47https://www.buraksenyurt.com/post/AspNet-40-Heryerde-CacheAsp.Net 4.0 - Heryerde Cache [Beta 2]2009-11-18T04:20:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2009%2f11%2fblg103_Giris.jpg" alt="" />Merhaba Arkadaşlar,</p>
<p>Kronometrelerinizi hazır edin! Bu yazımızda <strong>Absolute</strong> ve <strong>Sliding Expiration </strong>modelinde ön bellekleme işlemlerini <strong>Windows </strong>tabanlı bir uygulama üzerinde gerçekleştiriyor olacağız. Durun bir dakika...<strong>Windows</strong> mu? Evet evet yanlış duymadınız <strong>Windows</strong>. Aslında başlıktaki konu ile tamamen tezat bir durum. Gerçekten de öyle mi acaba? Gelin şu meseleyi açıklığa kavuşturalım. <img title="Smile" src="/editors/tiny_mce3/plugins/emotions/img/smiley-smile.gif" alt="Smile" border="0" /></p>
<p>Ön bellekleme işlemleri ile performans arttırımı çoğunlukla web uygulamalarında akla gelen bir konudur. Ancak gerçek hayat uygulamaları sadece Web tabanlı değildir. <strong>Windows Forms, WPF</strong> gibi masaüstü uygulamalarından tutunda, katmanları ifade eden <strong>Class Library'</strong> lere kadar çok çeşitli ürünler yer almaktadır. Dolayısıyla performans kazanımı, iş yükünün hafifletilmesi için ön bellekleme işleminin sadece Web uygulamalarına bağımlı kalması düşünülemez. Peki Web ortamı dışında <strong>ön bellekleme(Caching)</strong> teknikleri için hangi imkanlar bulunmaktadır?</p>
<p>Aslında listenin başında <strong>System.Web.Caching.dll</strong> assembly' ının Web dışındaki uygulamalara referans edilerek kullanılmasının yer aldığını söyleyebiliriz. Ne varki bir Windows uygulamasına <strong>Web</strong> alanına ait bir <strong>Assembly'</strong> ın referans edilmeside son derece gariptir. <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /> Daha etkili bir yöntem olarak <strong>Enterprise Library</strong> içerisinde yer alan <strong>Caching</strong> bloğunun kullanılması tercih edilebilir. Bunların haricinde henüz incelediğim ve yakında sizinle ilk bilgilerimi paylaşacağım <strong>Velocity</strong> projesi de yer almaktadır ki <strong>dağıtık ön bellekleme(Distributed Caching)</strong> ve dolayısıyla <strong>Cache</strong> üzerinde<strong> Load Balancing</strong> vb imkanlar sunmakta olan bir projedir. Ancak <strong>Asp.Net 4.0'</strong> ın duyurulması ile birlikte özellikle Overivew dökümünında belirtilen yeni bir koz daha bulunmaktadır. <strong>System.Runtime.Caching.dll</strong> <strong>assembly'</strong> ı. Biz bu gün geliştireceğimiz örnekte <strong>ObjectCache</strong> tipinden yararlanarak ön bellekleme işlemlerini yapmaya çalışacağız.</p>
<p><img src="/pics/2009%2f11%2fblg103_Browse.gif" alt="" /></p>
<p>Bu assembly içerisinde yer alan tiplerden yararlanarak özel <strong>Cache</strong> sağlayıcılar, tipler geliştirebileceğimiz gibi <strong>In-Memory</strong> ön bellekleme yeteneklerini web dışındaki uygulamalarda da kullanabiliriz. Üstelik <strong>.Net Framework</strong> içerisine dahil edilmiş olması, <strong>Enterprise Library</strong> gibi üçüncü parti kurulumlara ihtiyaç duymayışı, kullanımının Web tarafındaki <strong>Cache</strong> nesnesi ile neredeyse aynı olmasıda avantaj olarak görülebilir. Bu yazımızda söz konusu ön bellekleme tekniklerine sadece iki açıdan bakıyor olacağız. <strong>Sliding</strong> ve <strong>Absolute Expiration </strong>tipli ön bellekleme işlemleri.</p>
<p>Bilindiği üzere ön bellekte tutulacak olan verinin ne kadar süre ile duracağının belirtilmesi<strong> Absolute Expiration</strong> tekniğini ilgilendiren bir meseledir. Diğer yandan belirtilen süre içerisinde ön bellekte tutulan <strong>Cache</strong> nesnesine talep gelmesi sonrası, o andan itibaren tekrardan belirtilen süre kadar yaşam ömrünün uzatılması da <strong>Sliding Expiration</strong> tekniğini ilgilendiren bir konudur. Bunlara ek olarak ön belleklemede popüler olarak kullanılan <strong>bağımlılık(Dependency)</strong> gibi tekniklerde bulunmaktadır. Buna görede <strong>Cache</strong> nesnesinin içeriğinin tazelenmesinin bir sebebe bağımlı hale getirilmesi sağlanabilir. Bu sebep basit bir dosyadaki değişiklik olabilir örneğin.</p>
<p>Dilerseniz hiç vakit kaybetmeden <strong>Visual Studio 2010 Ultimate Beta 2</strong> üzerinde basit bir <strong>Windows </strong>uygulması geliştirerek yolumuza devam edelim. Örneğimizde <strong>Product</strong> tipinden nesne örnekleri tutan generic bir <strong>List<T></strong> koleksiyonunun içeriğinin <strong>Absolute</strong> ve <strong>Sliding </strong>olarak ön belleklenmesi işlemlerini göz önüne alıyor olacağız. Tabi ilk etapta <strong>System.Runtime.Caching</strong> assembly' ının <strong>Win Forms </strong>uygulamasına referans edilmesi gerekmektedir.</p>
<p><img src="/pics/2009%2f11%2fblg103_AddReference.gif" alt="" /></p>
<p>WinForms uygulamamızın basit ekran görüntüsü ise aşağıdaki gibidir.</p>
<p><img src="/pics/2009%2f11%2fblg103_Form.gif" alt="" /></p>
<p>Gelelim kodlarımıza;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.Runtime.Caching;
using System.Windows.Forms;
namespace UsingObjectCache
{
public partial class Form1
: Form
{
// Cache nesnelerine erişmek için kullanılan tip tanımlanır
ObjectCache cachedObject;
public Form1()
{
InitializeComponent();
// Varsayılan MemoryCache referansı elde edilir
cachedObject = MemoryCache.Default;
}
// Cache üzerinden Products Key değerine sahip içeriği getirmek için kullanılan olay metodudur
private void btnGet_Click(object sender, EventArgs e)
{
// Eğer ProductList Key değerine sahip ön belleklenmiş bir içerik var ise
if (cachedObject["Products"] != null)
{
// Indeksleyici yardımıyla ilgili Cache nesnesi çekilir
lstProducts.DataSource = cachedObject["Products"] as List<Product>;
lblInformation.Text = "Ürün listesi içeriği ön bellekten getirildi";
}
else
{
lblInformation.Text = "Cache içerisinde söz konusu liste yok\n Bilgiler tekrardan üretilecek";
lstProducts.DataSource = CreateProductList();
}
}
// Cache' lenen veriyi belirli bir süreliğine tutmak için gerekli ayarlamaları yapan olay metodudur.
private void btnAbsoluteExpiration_Click(object sender, EventArgs e)
{
// Zaten Products isimli bir Cache içeriği yoksa, bu Key değerine sahip olan bir Cache içeriği oluşturulur ve o andan itibaren 30 saniye süreyle ön bellekleneceği belirtilir.
if (cachedObject["Products"] == null)
if (cachedObject.Add("Products", CreateProductList(), new DateTimeOffset(DateTime.Now.AddSeconds(30))))
lblInformation.Text = "Absolute Expiration(30 Seconds)";
}
// Kayan süreli Cache' leme için gerekli işlemleri yapan olay metodudur.
// Buna göre 30 saniyelik süre dolmadan gelen talepler, Cache' te tutulmas süresini o andan itibaren tekrar 30 saniye ileri götürürler
private void btnSlidingExpiration_Click(object sender, EventArgs e)
{
// Absolute Expiration, Sliding Expiration, Dependency gibi Cache çeşitlerini istersek ilke(Policy) olarak tanımlayabiliriz.
CacheItemPolicy policy = new CacheItemPolicy();
policy.SlidingExpiration = TimeSpan.FromSeconds(30);
if (cachedObject["Products"] == null)
if (cachedObject.Add("Products", CreateProductList(), policy))
lblInformation.Text = "Sliding Expiration(30 Seconds)";
}
// Maliyetli olduğu varsayılan ve içeriği ön bellekte tutulabilecek olan sembolik bir fonksiyonellik
private List<Product> CreateProductList()
{
return new List<Product>
{
new Product{ ProductId=10, Name="Bardak", ListPrice=1.23M},
new Product{ ProductId=11, Name="Tabak", ListPrice=1.25M},
new Product{ ProductId=12, Name="Çatal", ListPrice=0.55M}
};
}
}
// Yardımcı tip
class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal ListPrice { get; set; }
public override string ToString()
{
return String.Format("{0}|{1} {2}", ProductId.ToString(), Name, ListPrice.ToString("C2"));
}
}
}</pre>
<p><strong>Cache</strong> yönetimi için <strong>MemoryCache.Default </strong>özelliğinin ürettiği <strong>ObjectCache </strong>nesne referansı kullanılmaktadır. <strong>ObjectCache </strong>tipinin indeksleyicisinden yararlanılarak ön bellekte tutulan bir <strong>Key</strong> değerine ve doğal olarak işaret ettiği <strong>Object </strong>tipinden içeriğe ulaşmak mümkündür. Diğer yandan <strong>Add</strong> ve <strong>Set</strong> gibi metodlar yardımıyla ön belleğe veri atılmasıda sağlanabilir. Burada dikkat çekici noktalardan biriside ön bellekleme tipi için <strong>ilkelerden(Policy)</strong> yararlanılabilmesidir. Örneğimizde <strong>Sliding Expiration</strong> için <strong>CacheItemPolicy</strong> nesne örneği tanımlanmıştır. Bu nesne örneği aslında ön bellekleme ilkesini ifade etmektedir. Önbelleğe atılacak nesne içeriğinin bu ilkeye göre tutulacağını belirtmek içinse <strong>Add</strong> metoduna parametre olarak verilmesi yeterli olmuştur. Aslında <strong>Add</strong> metodunun aşırı yüklenmiş versiyonlarından birisi de <strong>Absolute Expiration</strong> tekniğine göre parametre almaktadır ki buda örneğimizde kullanılmıştır.</p>
<p>Gelelim testlerimize. Hatırlarsanız kronometrelerinizi hazır tutmanızı söylemiştim. Bu tabiki işin şakası <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Nitekim kodun içerisinde de test amaçlı olarak bir kronometre kullanılabilir. Çalışma zamanındaki testlerimizi aşağıdaki adımlarda olduğu gibi geliştirelim.</p>
<p><strong>1 -</strong> Uygulama başlatıldıktan sonra Get başlıklı düğmeye basılır ve aşağıdaki ekran görüntüsü ile karşılaşılır.</p>
<p><img src="/pics/2009%2f11%2fblg103_Test1.gif" alt="" /></p>
<p>Get içerisinde yapılan çağrıda <strong>ObjectCache</strong> içerisinde <strong>Products</strong> isimli bir <strong>Key</strong> bulunmadığından ürün listesinin maliyeti yüksek olduğu düşünülen bir metod ile üretilmesi gerçekleştirilir.</p>
<p><strong>2 -</strong> 1nci testten sonra Absolute Expiration veya Sliding Expiration düğmelerinden birisi kullanılır. Absolute Expiration başlıklı düğme tıklandığında aşağıdaki ekran görüntüsü ile karşılaşılmalıdır.</p>
<p><img src="/pics/2009%2f11%2fblg103_Absolute.gif" alt="" /></p>
<p>Buna göre Product listesi ön bellekte <strong>30</strong> <strong>saniye</strong> süreyle saklanacaktır. Süre dolmadan Get düğmesine basılırsa aşağıdaki ekran görüntüsü ile karşılaşılmalıdır.</p>
<p><img src="/pics/2009%2f11%2fblg103_AbsoluteTest.gif" alt="" /></p>
<p>Şimdi <strong>30 saniyelik</strong> süre sona erdikten sonra tekrar Get düğmesine basılırsa artık ön bellekte bir veri tutulmadığından ürün listesi üretim işleminin tekrar yapıldığı görülmelidir.</p>
<p><strong>3 -</strong> 2nci testin bitmesinden sonra seçiminize göre diğer ön bellekleme tekniğini ele alabilirsiniz. Benim sırama göre şimdi <strong>Sliding Expiration</strong> testinin yapılması gerekmektedir. Program açık iken <strong>Sliding Expiration </strong>başlıklı düğmeye asarsanız aşağıdaki ekran görüntüsü ile karşılaşırsınız.</p>
<p><img src="/pics/2009%2f11%2fblg103_Sliding.gif" alt="" /></p>
<p>Bu adımdan sonra <strong>30 saniyelik</strong> süre dolmadan tekrar Get düğmesine basarsanız içeriğin ön bellekten getirildiğini görebilirsiniz. Ancak önemli olan nokta şudur; <strong>Ön bellekte durma süresi, 30 saniyelik süre içerisinde Get düğmesine bastığınız andan itibaren 30 saniye sonrasına uzamasıdır</strong>.</p>
<p><strong>4 -</strong> Uygulamayı herhangibir <strong>Cache</strong> tekniği uygulandıktan sonra ilgili süreler aşılmadan kapatıp tekrar açınız ve yine Get düğmesine basınız. Bu durumda içeriğin ön bellekten değil tekrardan üretim ile geldiğini görmelisiniz ki bu son derece doğaldır. Çünkü uygulama sonlandırılmış ve kendisi için ayrılan bellek içeriği bir sonraki uygulama örneği için geçersiz hale gelmiştir. Hımmm...!!! Aslında bu çokda istediğimiz bir vaka olmayabilir.</p>
<p>Tüm bunlar bir yana en iyi test yöntemlerinden biriside uygulmayı <strong>Debug</strong> ederek incelemeniz olacaktır ki bunu yapmanızı şiddetle tavsiye ederim. Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2009%2f11%2fUsingObjectCache.rar">UsingObjectCache.rar (42,82 kb)</a></p>2009-11-18T04:20:00+00:00asp.net 4.0 beta 2asp.netbsenyurtAslında listenin başında System.Web.Caching.dll assembly' ının Web dışındaki uygulamalara referans edilerek kullanılmasının yer aldığını söyleyebiliriz. Ne varki bir Windows uygulamasına Web alanına ait bir Assembly' ın referans edilmeside son derece gariptir...https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=e1719995-8a84-4da7-ae62-1670865865ea2https://www.buraksenyurt.com/trackback.axd?id=e1719995-8a84-4da7-ae62-1670865865eahttps://www.buraksenyurt.com/post/AspNet-40-Heryerde-Cache#commenthttps://www.buraksenyurt.com/syndication.axd?post=e1719995-8a84-4da7-ae62-1670865865eahttps://www.buraksenyurt.com/post/AspNet-40-Custom-Cache-ProviderAsp.Net 4.0 - Özelleştirilmiş Cache Sağlayıcısı(Custom Cache Provider) [Beta 2]2009-11-17T06:10:00+00:00bsenyurt<p><img style="float: left;" src="/pics/2009%2f11%2fblg102_Giris.jpg" alt="" />Merhaba Arkdaşlar,</p>
<p>Çok çok uzun zamandır <strong>Asp.Net</strong> üzerine eğilmiyordum. Hem tasarım yönünden kabiliyetsiz olmam<em>(iki rengi bir araya getir deseler kesin uyumsuz renkler çıkartırım)</em> hemde servis yönelimli mimari dünyasına dalmış olmamın bunda büyük bir rol oynadığını itiraf etmek isterim. Yine de <strong>Asp.Net 4.0</strong> ile birlikte gelen yenilikleri okuyunca biraz olsun araştırmak ve edindiğim tecrübeleri sizlere aktarmak istedim.</p>
<p>Dikkatimi çeken ilk özellik <strong>ön</strong> <strong>bellekleme(Caching)</strong> sisteminin genişletilebilmesi ile alakalıydı. Bilindiği üzere web uygulamalarında performansı arttırmanın en etikili yollarından biriside sunucu tarafındaki yükü azaltarak mümkün olabilmektedir. Bu manada istemci tarafına, sunucu üzerinde ön belleğe atılmış hazır veri çıktılarını göndermek etkili bir yaklaşımdır. <strong>Asp.Net</strong> tarafında ön bellekleme için farklı teknikler kullanılabilir. <strong>Son süre bildirimli(Expire Date), uzatmalı(Sliding), bağımlı(Dependency, SqlCacheDependency, FileDependency gibi) </strong>vb...Üstelik ön belleklenecek veri içeriği sayfa bazında, Web User Control bazında vb olabilir. Yine de eksik olan bir şeyler vardır. Herşeyden önemlisi ön bellekleme gerçekten bellek üzerinde yapılmaktadır. <img title="Smile" src="/editors/tiny_mce3/plugins/emotions/img/smiley-smile.gif" alt="Smile" border="0" /> Basit bir blog sitesi için ön belleklenecek veri içeriği çok büyük problem teşkil etmeyebilir.</p>
<p>Ne varki çok sayıda kullanıcıya hizmet veren portallerde ön belleklenen nesnelerin sayısının, içeriğinin artması, beraberinde belleğinde ölçeklendirilmesi ihtiyacını doğurmaktadır. Buna göre daha çok bellek almak gibi bir maliyet altına girmek gerekebilir. Bu duruma karşın <strong>Asp.Net 4.0</strong> ile birlikte ön bellekleme işlemini daha kolay bir şekilde özelleştirebilme şansına sahibiz. Bir başka deyişle kendi <strong>Cache Provider</strong> tiplerimizi geliştirerek ön bellekleme yerini ve modelini değiştirebilir kendi algoritmalarımızı işin içerisine katabiliriz. Tabi <strong>Beta 2</strong> sürümüne göre bu konuyu incelediğimden ve yazıyı hazırladığım tarih itibariyle internet üzerinde çok fazla kaynak bulamadığımdan halen daha pek çok noktada soru işareti vuku bulmuş durumdadır. Bu nedenle zaman içerisinde bu konuda çok daha detaylı bilgiye ulaşabileceğimizi düşünmekteyim.</p>
<p>Dilerseniz hiç vakit kaybetmeden örnek bir senaryo üzerinden hareket edelim. Amacımız web uygulamamızda kullanılan bir<strong> Web User Control'</strong> ün içeriğini zamana bağlı olarak ön belleklerken, dosya tabanlı bir sistemden yararlanmak. Buna göre ön belleğe atılacak olan nesne içeriğinin fiziki olarak bir dosya içerisine <strong>serileştirmeyi(Serialization)</strong> planlıyoruz. Çok doğal olarak web uygulaması içerisinde n sayıda sayfa ve n sayıda Web User Control olabilir. Buda fiziki olarak her <strong>Web User Control</strong> için birden fazla serileştirilmiş veri içeriği tutan dosya anlamına gelmektedir. Diğer yandan sistemimizde <strong>Expire</strong> eden dosyaların silinmesi işlemlerini de göz önüne almalıyız. Yani bu dosyaların içerikleri gelen yeni bir talep sonrasında yeniden üretilmeli, talep gelmediği ve Duration dolduğunda ise silinmelidir şeklide bir yol tercih ediyoruz.</p>
<p>Peki <strong>Asp.Net 4.0</strong> tarafında bu tip özelleştirilmiş bir <strong>Cache</strong> sağlayıcısı için ne getirilmiştir?</p>
<p>Aslında tahmin etmek oldukça kolaydır. Var olan bir sisteme yeni bir eklenti ilave etmek istiyorsak tercih edilecek yollardan birisi, sistemin bize söylediği kurallara uymaktır. <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Şimdilik bu kuralı söyleyen <strong>OutputCacheProvider</strong> isimli <strong>abstract </strong>bir sınıftır. Söz konusu sınıf <strong>Add, Get, Set</strong> ve <strong>Remove </strong>isimli abstract metodlar içermektedir. Buna göre geliştireceğimiz<strong> Cache Provider</strong> sınıfının bu fonksiyonları mutlaka ve mutlaka ezmesi gerekmektedir. Bir başka deyişle <strong>Cache</strong> sistemi için gerekli temel <strong>CRUD</strong> operasyonlarının tarafımızdan uygulanması gerekmektedir. Peki yeterli midir? Elbette değildir.</p>
<p>Bir şekilde web uygulaması tarafına, kendi özel <strong>Cache</strong> sağlayıcımızı kullanabileceğimizi ifade etmemiz gerekecektir ki bunun içinde tahmin edeceğiniz üzere <strong>web.config</strong> dosyasından yararlanılacaktır. Geliştireceğimiz örnekte özel <strong>Cache</strong> sağlayıcısını çok kısıtlı olarak kullanabileceğiz. İlk hedefimiz senaryomuzda belirttiğimiz üzere<strong> Web User Control</strong> içeriklerini ön belleklemektir. Buna göre standart olarak kullandığımız <strong>OutputCache</strong> direktifinde bir şekilde özel Cache sağlayıcımızı da işaret edebilmeliyiz ki buda oldukça kolaydır. Öyleyse hiç vakit kaybetmeden örneğimizi geliştirmeye başlayalım. İlk olarak <strong>DiskCacheProvider</strong> isimli <strong>OutputCacheProvider </strong>tipinden türeyen aşağıdaki sınıfı geliştirmeliyiz.</p>
<p><strong>DiskCacheProvider sınıfına ait diagram;</strong></p>
<p><img src="/pics/2009%2f11%2fblg102_ClassDiagram.gif" alt="" /></p>
<p><strong>Custom Provider kodu;</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Timers;
using System.Web.Caching;
using System.Collections.Concurrent;
namespace CustomCaching
{
public class DiskCacheProvider
: OutputCacheProvider
{
// Expire olan Cache nesnelerini tutan dosyaların silinmesi için bir Timer nesnesi kullanılır
Timer watcher;
// Cache nesnelerinin serileştirildiği dosyaların tutulduğu klasör
string cachePath = "C:\\Cache\\";
// Dosya adı ve Expire zamanlarını tutan koleksiyon nesnesi. Eş zamanlı çıkartma işlemine destek verebilmek için .Net 4.0 ile gelen Concurrent koleksiyonlardan birisi kullanılmaktadır.
ConcurrentDictionary<string, DateTime> cacheExpireList;
// Yapıcı metod içerisinde gerekli nesne başlatma işlemleri yapılır
public DiskCacheProvider()
{
cacheExpireList = new ConcurrentDictionary<string, DateTime>();
// Timer nesne örneği 3 saniyede bir Elapsed olayını tetikleyecektir
watcher = new Timer(3000);
// Elapsed olayı içerisinde Expire olan output cache dosyalarının bulunması sağlanır
watcher.Elapsed += (o, e) =>
{
// Koleksiyonda duran Expire zamanı ile güncel zaman karşılaştırılarak bir sonuca gidilmeye çalışılır
var discardedList = from cacheItem in cacheExpireList
where cacheItem.Value < DateTime.Now
select cacheItem;
// Expire olmaya aday olan Cache nesnelerine ait dosyalar için Remove metodu çağırılır.
// Eğer normal bir Dictionary<T,K> koleksiyonu kullanılırsa çalışma zamanında InvalidOperationException alınabilir. Nitekim discardedList ile gezilirken cacheExpireList' in değişmiş olma ihtimali bulunabilir. Bu nedenle ConcurrentDictionary<T,K> kullanılması tercih edilmiştir
foreach (var discarded in discardedList)
{
Remove(discarded.Key);
// Koleksiyondan çıkartılır
DateTime discardedDate;
cacheExpireList.TryRemove(discarded.Key, out discardedDate);
}
};
// Timer nesne örneği başlatılır
watcher.Start();
}
// utcExpiry parametresi, Cache için Expire süresini belirtir
public override object Add(string key, object entry, DateTime utcExpiry)
{
FileStream fs = new FileStream(String.Format("{0}{1}.binary", cachePath, key), FileMode.Create, FileAccess.Write);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, entry);
fs.Close();
cacheExpireList.TryAdd(key, utcExpiry.ToLocalTime());
return entry;
}
// Cache' den nesnesi elde etmek için kullanılan metoddur
// OutputCacheProvider abstract sınıfından gelen ve ezilmesi mecburi olan bir fonksiyondur.
public override object Get(string key)
{
string path = String.Format("{0}{1}.binary", cachePath, key);
// Örnekteki sistem Cache nesne içeriklerini dosya tabanlı olarak tutmaktadır. Bu noktada dosyanın sistemde var olup olmadığına bakılarak Cache' lenen bir içerik olup olmadığı sonucuna varılabilir
if (File.Exists(path))
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryFormatter formatter = new BinaryFormatter();
// Ters serileştirme işlemi ile dosya içeriğinden Cache' lenen nesnenin canlandırılması sağlanır
object result = formatter.Deserialize(fs);
fs.Close();
return result;
}
else
return null;
}
// Cache nesnesinin kaldırılması için kullanılan metoddur. OutputCacheProvider abstract sınıfından gelen ve ezilmesi mecburi olan bir fonksiyondur.
// OutputCacheProvider abstract sınıfından gelen ve ezilmesi mecburi olan bir fonksiyondur.
public override void Remove(string key)
{
string path = String.Format("{0}{1}.binary", cachePath, key);
if (File.Exists(path)) // Eğer dosya var ise Cache' lenen bir nesne var olduğu sonucuna ulaşabiliriz
{
// Dosya silinir
File.Delete(path);
}
}
// Set metodunda Cache in saklanması işlemleri gerçekleştirilir. Genellikle overwrite mantığına göre çalışır. Yani Cache' lenen nesne varsada üzerine yazılması yoluna gidilir
// OutputCacheProvider abstract sınıfından gelen ve ezilmesi mecburi olan bir fonksiyondur.
public override void Set(string key, object entry, DateTime utcExpiry)
{
// Cache' lenen içerik varsa overwrite işlemi yapılır.
string path = String.Format("{0}{1}.binary", cachePath, key);
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
BinaryFormatter formatter = new BinaryFormatter();
// Cache nesnesi serileştirilerek dosyaya yazdırılır
formatter.Serialize(fs, entry);
fs.Close();
// Cache' lenen nesne serileştirildiği dosyada tutulduğundan expire sürelerini takip edebilmek için ilgili koleksiyonda bilgilendirme yapılır.
cacheExpireList.TryAdd(key, utcExpiry.ToLocalTime());
}
}
}</pre>
<p>Şimdi çok kısaca neler yaptığımıza bir bakalım. Cache sağlayıcımız Cache' lenecek olan nesneleri varsayılan olarak <strong>C:\Cache</strong> isimli bir klasör altında dosyalamaktadır<em>(Aslında bu bilgide ilgili provider' a örneğin yapıcı metod yardımıyla web.config dosyası üzerinden geçirilebilir)</em>. Söz konusu nesne içerikleri ilgili dosyalara <strong>binary</strong> formatta serileştirilmektedir. Bu amaçla <strong>BinaryFormatter</strong> tipinden yararlanılmaktadır. Özellikle Cache' e nesne atma işlemi sırasında devreye giren <strong>Set</strong> metodu içerisinde, dosya adı için <strong>key</strong> parametresininin kullanıldığına dikkat edilmelidir. Hatta asıl dikkat edilmesi gereken nokta her cache için değişik bir key değerinin üretildiğidir<em>(Ancak ispatını yapamadım henüz bunu belirteyim)</em>. </p>
<p>Diğer yandan <strong>Expire</strong> süreleride ilgili metodlara(örneğin Set) parametre olarak gelmektedir. Bu süre bilgilerinden yararlanılarak ön bellekten düşürme işlemleri yapılmalıdır. Örneği geliştirirken beklentilerimi boşa çıkaran noktalardan biriside aslında Expire süreleri ile ilişkilidir. Şöyleki; örneği geliştirirken <strong>Remove</strong> metodunun belirtilen <strong>Duration</strong> süresi sonlandığında otomatik olarak devreye gireceğini tahmin etmiştim. Ancak bu şekilde olmadı <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /> Bu nedenle Cache' lenen dosyaların zamanı geldiğinde silinmesi için bir mekanizmanın geliştirilmesi gerekiyordu. Bu amaçla <strong>Timer</strong> nesnesinden yararlanarak <strong>Elapsed</strong> olayı içerisinde gerekli silme işlemlerini gerçekleştirmeyi tercih ettim. Çok doğal olarak hangi dosyaların silinmesi gerektiğini anlayabilmek içinde basit bir koleksiyon tabanlı yapıyı tercih ettim. Tabiki Thread Safe bir yapı söz konusu değil. Hatta eş zamanlı gerçekleşebiliecek çıkarma işlemlerine karşın kolaya kaçıp <strong>ConcurrentCollection<T,K> </strong>kullandığımı ifade edebilirim. Aslına bakarsanız şu an için tek derdim gerçekten özelleştirilmiş bu Cache sağlayıcısının çalışıp çalışmadığını görebilmek. <img title="Cool" src="/editors/tiny_mce3/plugins/emotions/img/smiley-cool.gif" alt="Cool" border="0" /></p>
<p>Şimdi bu <strong>Cache Provider</strong> tipini web uygulamamızda nasıl kullanacağımızı belirtmemiz gerekiyor. Bu amaçla <strong>Web.config</strong> dosyası içerisinde aşağıdaki eklemeleri yapmamız yeterli olacaktır.</p>
<p><strong>web.config içeriği;</strong></p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<caching>
<outputCache defaultProvider="AspNetInternalProvider">
<providers>
<add name="DiskBasedCacheProvider" type="CustomCaching.DiskCacheProvider,CustomCaching"/>
</providers>
</outputCache>
</caching>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration></pre>
<p>Dikkat edileceği üzere <strong>providers</strong> elementi içerisinde <strong>DiskBasedCacheProvider </strong>isimli bir bildirim yer almakta ve geliştirdiğimiz <strong>DiskCacheProvider</strong> tipini işaret etmektedir. Bununla birlikte <strong>outputCache</strong> elementinin <strong>defaultProvider</strong> niteliğinde yer alan <strong>AspNetInternalProvider</strong> değeri, standart <strong>Asp.Net</strong> ön bellekleme sisteminin kullanılacağını ifade etmektedir. Örneğimize aşağıdaki basit Web User Control' ü ekleyerek devam edebiliriz.</p>
<p><strong>Web User Control içeriği;</strong></p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CurrentDateTime.ascx.cs" Inherits="CustomCaching.CurrentDateTime" %>
<%@ OutputCache Duration="20" VaryByParam="none" ProviderName="DiskBasedCacheProvider" %>
<style type="text/css">
.style1
{
color: #FFCC00;
}
</style>
<div style="background-color:Gray">
<strong><span class="style1">Güncel Zaman :
</span>
<asp:Label ID="Label1" runat="server" Text="Label" CssClass="style1"></asp:Label>
</strong>
</div></pre>
<p><strong>OutputCache</strong> direktifi içerisindeki <strong>ProviderName</strong> niteliği mutlaka dikkatinizi çekmiştir. Burada <strong>DiskBasedCacheProvider</strong> isimli bir değer kullanılmaktadır. Buda bilindiği üzere <strong>web.config</strong> dosyasında yer alan özel <strong>Cache</strong> sağlayıcı tipini işaret etmektedir. Duration değeri <strong>20</strong> olduğu için söz konusu <strong>Web User Control</strong> içeriğinin <strong>20</strong> <strong>saniye</strong> süreyle tutulması söz konusudur.</p>
<p><strong>Web User Control kodu;</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace CustomCaching
{
public partial class CurrentDateTime : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
}
}
}</pre>
<p>Ve hemen arkasından basit bir Web sayfası...</p>
<p><strong>Default.aspx içeriği;</strong></p>
<pre class="brush:html;auto-links:false;toolbar:false" contenteditable="false"><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CustomCaching.Default" %>
<%@ Register src="CurrentDateTime.ascx" tagname="CurrentDateTime" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
Default Sayfası için Güncel Zaman :
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</div>
<uc1:CurrentDateTime ID="CurrentDateTime1" runat="server" />
<p>
İkinci Web User Control</p>
<uc1:CurrentDateTime ID="CurrentDateTime2" runat="server" />
</form>
</body>
</html></pre>
<p><strong>Default.aspx kodu</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace CustomCaching
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
}
}
}</pre>
<p>Tahmin edileceği üzere o anki zaman bilgisini hem aspx sayfası hemde <strong>Web User Control</strong> içerisinden göstererek bir karşılaştırma yapmaya çalışacağız. Öyleki; eğer Cache sağlayıcımız devreye girerse, Web User Control içeriği 20 saniyeliğine fiziki olarak tutulan bir dosyadan karşılanacak ve bu sebeple sayfanın zaman bilgisi değişirken kendisinin ki sabit olarak kalacak. Tabiki belirtilen <strong>Duration</strong> süresi kadar. Artık testlere başlayabiliriz. Size önerim indirdiğiniz örneği mutlaka <strong>Debug</strong> ederek incelemenizdir. Özellikle Set ve Get metodları ile Elpased olayında durmanızı tavsiye ederim. Ben ilk olarak aynı web sayfasına iki farklı talep gönderip aşağıdaki çıktıları elde ettim.</p>
<p><img src="/pics/2009%2f11%2fblg102_Runtime1.gif" alt="" /></p>
<p>Görüldüğü üzere iki farklı talep gönderilmiş ve özellikle ikince talepte Web User Control içerisindeki zamanın değişmediği görülmüştür. Çünkü bu içerik ilk talep ile birlikte <strong>20</strong> saniyeliğini fiziki olarak bir dosyaya serileştirilmiş ve bu zaman dilim içerisinde sürekli olarak ilgili dosyadan <strong>ters serileşerek(DeSerialization)</strong> getirilmiş bir <strong>HTML</strong> çıktısıdır. 20 saniyelik süre sona erdikten sonra sayfalarda herhangibir yeni talep oluşturmassak, ilgili fiziki dosyalarında Cache klasöründen silindiği gözlemlenir. Geliştirdiğimiz örnekte sadece <strong>Set, Get</strong> ve <strong>Remove </strong>metodları işlevsel durumdadır. Yani söz konusu vakaya göre <strong>Add</strong> metodu herhangibir sebeple çalışmamıştır.</p>
<p>Hemen bir noktayı aydınlığa kavuşturalım. Geliştirdiğimiz örnekte Web User Control' ün üretimi özel Cache sağlayıcısı içerisindeki serileştirme ve ters serileştirme gibi işlemlerin çıkarttığı maliyetten daha az olabilir. Yani aslında bu örneğe göre bir Cache sistemi kullanılmasına gerek duyulmaz. Bizim amacımız sadece özel bir Cache sağlayıcısının nasıl yazılabileceğini <strong>Asp.Net 4.0 Beta 2</strong> cephesinden incelemektir. Tabiki genişletilebilir Cache sisteminin daha esnek imkanlar sunacağıda belirtilmektedir. Aslında bu konu ile ilişkili özet bir bilgiyi <strong><a title="Asp.Net 4.0 Overivew" href="http://www.asp.net/LEARN/whitepapers/aspnet4/default.aspx" target="_blank">asp.net </a></strong>sitesinden indireceğiniz dökümanda bulabilirsiniz. Böylece geldik bir yazımızın daha sonuna. Tabiki buradaki eksikleri ve gereksinimleri en iyi değerlendirecek kişi sevgili arkadaşım <a title="Uğur Umutluoğlu (Asp.Net MVP)" href="http://www.umutluoglu.com/" target="_blank">Uğur Umutluoğlu' dur(Asp.Net MVP)</a>. Tekrardan görüşünceye dek hepinze mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2009%2f11%2fCustomCaching.rar">CustomCaching.rar (26,21 kb)</a></p>2009-11-17T06:10:00+00:00asp.net 4.0asp.netbsenyurtDikkatimi çeken ilk özellik ön bellekleme(Caching) sisteminin genişletilebilmesi ile alakalıydı. Bilindiği üzere web uygulamalarında performansı arttırmanın en etikili yollarından biriside sunucu tarafındaki yükü azaltarak mümkün olabilmektedir...https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=bd0163e3-5759-4bda-9304-03bc8ad77aa51https://www.buraksenyurt.com/trackback.axd?id=bd0163e3-5759-4bda-9304-03bc8ad77aa5https://www.buraksenyurt.com/post/AspNet-40-Custom-Cache-Provider#commenthttps://www.buraksenyurt.com/syndication.axd?post=bd0163e3-5759-4bda-9304-03bc8ad77aa5