https://buraksenyurt.com/Burak Selim Şenyurt - Enterprise Library2016-11-09T10:45:17+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://buraksenyurt.com/post/Caching-Application-Block-Merakc4b1Caching Application Block Merakı2009-06-20T17:52:00+00:00bsenyurt<p style="text-align: left;"><img style="float: right;" src="/pics/2009%2f6%2fblg34_1.jpg" alt="" />Merhaba Arkadaşlar, </p>
<p style="text-align: left;">Az önce 1966 yılında çevrilmiş olan ve küçüklüğümde bol bol izlediğim nefis bir filmi belkide 179ncu kez tekrardan seyrettim. Eskiler aşağıdaki resimden hangi film olabileceğini tahmin edebilirler. Yeni nesilden seyretmeyen varsa eğer <strong><a title="The Good, The Bad and The Ugly" href="http://en.wikipedia.org/wiki/The_Good,_the_Bad_and_the_Ugly" target="_blank">The Good, The Bad and The Ugly</a></strong> filmini mutlaka tedarik edip izlesinler. Peki bunun anlatacağım konu ile bir ilgisi var mı? Hayır yok. <img title="Cool" src="/editors/tiny_mce3/plugins/emotions/img/smiley-cool.gif" alt="Cool" border="0" /> Sadece off-topic bir giriş yapmak istedim.</p>
<p>Bu yazımda sizlere bahsetmek istediğim konu bir süredir boş vakitlerimde araştırıp incelediğim <strong>Caching Application Block</strong> yapısıdır. Açık kaynak olarak sunulan <strong><a title="Enterprise Library 4.1" href="http://www.microsoft.com/Downloads/details.aspx?familyid=1643758B-2986-47F7-B529-3E41584B6CE5&displaylang=en" target="_blank">Enterprise Library </a></strong>ürün ailesinin bir parçası olan bu bloğu, uygulamalarımızda performansı arttırmak adına ele alabiliriz. Bilindiği üzere günümüz uygulamalarında sıklıkla tekrar eden pek çok <strong>kıstas(Concern)</strong> bulunmaktadır. Örneğin <strong>hata yönetimi(Error Handling), loglama(Logging), şifreleme işlemleri(Cryptography), güvenlik(Security), doğrulama(Validation)</strong> veya <strong>veri erişim işlemleri(Data Access)</strong> bu kıstaslara örnek olarak gösterilebilir. Haliyle bu kavramlar çoğunlukla uygulamadan bağımsız olmaktadır. Nitekim uygulama çeşidi değişse bile, bu kıstasların bir kısmını veya tamamını kullanmak zorunda kalabiliriz.</p>
<p>Öyleyse uygulamalara bu kıstasların enjekte edilmesi sırasında gerekli hazırlıkları tekrar tekrar yapmamıza gerek bırakmayacak modellere ihtiyacımız vardır. <em>(<strong>Aspect Oriented Programming</strong> modelininde çözüm getirdiği sorunlardan birisidir bu aslında.)</em> Diğer taraftan, <strong>Enterprise Library</strong> gibi kütüphaneleri ele alaraktanda, bu kıstasların tamamını veya bir kısmını istediğimiz uygulamalarda değerlendirebiliriz. Bu sayede sürekli tekrar eden temel işlemlerle uğraşmak zorunda kalmayarak tamamen iş mantığına odaklanmamız mümkün olabilir. Üstelik Enterprise Library açık kaynak kodlu olduğundan, dilersek genişletebilir veya özelleştirebiliriz.</p>
<p><strong>Caching Application Block'</strong> un nasıl kullanıldığını anlatmak için oldukça hevesliyim<em>.(Dilerseniz benden çok daha iyi bir öğretici olan <a title="Enterprise Library 4.1 Hands-On-Lab" href="http://www.microsoft.com/Downloads/details.aspx?familyid=AB3F2168-FEA1-4FC2-B40C-7867D99D4B6A&displaylang=en" target="_blank">Hands-On-Lab' </a>leride kullanabilirsiniz ki şiddetle tavsiye ederim)</em> İlk etapta bize örnek bir senaryo gerekiyor. Ben elimde bir WCF servisi olduğunu, bu servisin XML tabanlı bir veri kaynağını kullanarak istemcilere ürün bilgilerini verdiğini düşündüm. Bununla birlikte, ürünlerin resim bilgileride fiziki dosyalarda ve sunucu tarafında yer almaktadır. İstemciler, listeleri çektikten sonra dilerlerse istedikleri bir ürünün resmini servisten talep edebilmektedir. Tabiki bu senaryoda performansı etkiliyen farklı faktörler vardır.</p>
<p>Herşeyden önce, servis yönelimli bir uygulama söz konusu olduğundan, istemci ve sunucu arasında taşınacak resim ve boyutu iletişim hızını ve performansını doğrudan etkileyecektir. <em>(Burada performans için resmin MIME protokolüne göre taşınması veya parçalara bölünerek aktarılması düşünülebilir.)</em> Diğer taraftan, istemcinin bir ürün resmini talep etmesi durumunda, sunucu tarafında resmin fiziki dosyadan tedarik edilerek istemci tarafına gönderilecek şekilde hazırlanması durumunda da performans kaybı söz konusu olacaktır. İşte biz <strong>Caching Application Block</strong> yapısını, servis tarafında resmin hazırlanması aşamasında ele alabiliriz. Yinede şunu vurgulamakta yarar vardır. WCF servisi web tabanlı olarak yayınlandığında pekala Asp.Net motorunun var olan önbellekleme modüllerinide kullanılabilir. Dolayısıyla senaryomuzu sadece <strong>Caching Application Block'</strong> un kullanımını öğrenmek amacıyla geliştirdiğimizi göz önüne almamızda yarar vardır. Hatta istemcinin asenkron olarak erişmesi veya servis tarafında paralel hesaplamalar yapılması gibi senaryoları hiç işin içerisine katmıyoruz bile.</p>
<p>Önce servis tarafını ele alalım. Servis tarafında veri kaynağı olarak Products.xml isimli bir dosya kullanılmaktadır.</p>
<p><img src="/pics/2009%2f6%2fblg34_2.gif" alt="" /></p>
<p><strong>XML</strong> içeriğinde basit olarak ürünün Id değeri, adı, liste fiyatı ve resim dosyası adı bilgileri tutulmaktadır. Resimler ise WCF Service uygulamasında <strong>ProductImages</strong> isimli bir fiziki klasörde yer almaktadır.</p>
<p><img src="/pics/2009%2f6%2fblg34_3.gif" alt="" /></p>
<p>XML içeriğini istemci tarafında sunarken Product isimli serileştirilebilir bir tipten yararlanıyor olacağız.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Runtime.Serialization;
namespace ProductServices
{
[DataContract]
public class Product
{
[DataMember]
public int ProductId { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal ListPrice { get; set; }
}
}</pre>
<p>Servis sözleşmesi ise aşağıdaki kod parçasında olduğu gibidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Collections.Generic;
using System.Drawing;
using System.ServiceModel;
namespace ProductServices
{
[ServiceContract]
public interface IPhotoService
{
[OperationContract]
List<Product> GetProducts();
[OperationContract]
byte[] GetPhoto(int productId);
}
}</pre>
<p>Sözleşmeyi uygulayan tipimizin kodları ise şu şekildedir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace ProductServices
{
public class PhotoService
: IPhotoService
{
public List<Product> GetProducts()
{
XDocument doc = XDocument.Load(ConfigurationManager.AppSettings["XmlSourcePath"]);
List<Product> products = (from p in doc.Element("Products").Elements("Product")
select new Product
{
ProductId=Convert.ToInt32(p.Element("Id").Value),
Name=p.Element("Name").Value,
ListPrice=Convert.ToDecimal(p.Element("ListPrice").Value)
}).ToList<Product>();
return products;
}
#region IPhotoService Members
public byte[] GetPhoto(int productId)
{
XDocument doc=XDocument.Load(ConfigurationManager.AppSettings["XmlSourcePath"]);
string imageFileName = (from p in doc.Element("Products").Elements("Product")
where p.Element("Id").Value == productId.ToString()
select p.Element("ImageFileName").Value).Single();
string imagePath = Path.Combine(ConfigurationManager.AppSettings["ImagesPath"], imageFileName);
return File.ReadAllBytes(imagePath);
}
#endregion
}
}</pre>
<p>Görüldüğü üzere, <strong>XML</strong> içeriğini sorgulama kısımlarında <strong>XLINQ</strong> ifadelerinden yararlanılmaktadır. <strong>GetProducts</strong> metodu, <strong>List<Product></strong> koleksiyonu tipinden bir referans döndürmektedir. Bununla birlikte herhangibir ürünün resmi, <strong>GetPhoto</strong> metodu yardımıyla <strong>byte[]</strong> dizisi olacak şekilde üretilmektedir. <strong>Products.xml</strong> dosyası ve resimlerin kök adres bilgileri <strong>web.config</strong> dosyasında <strong>appSettings</strong> kısmında tutulmaktadır. Bu nedenle söz konusu konfigurasyon bilgilerin alınabilmesi için, <strong>ConfigurationManager</strong> tipinden yararlanıldığı görülmektedir. Servisimiz basicHttpBinding bağlayıcı tipi üzerinden sunulmaktadır. Dolayısıyla web.config dosyasındaki servis ayarları aşağıda görüldüğü gibidir.</p>
<p><img src="/pics/2009%2f6%2fblg34_4.gif" alt="" /></p>
<p>Peki ya istemci tarafı? Bu uygulamayı aşağıdaki tasarıma sahip basit bir WinForms programı olarak düşünebiliriz aslında.</p>
<p><img src="/pics/2009%2f6%2fblg34_5.gif" alt="" /></p>
<p>İstemci uygulamaya servis referansının eklenmesinin ardından kodlarıda aşağıdaki gibi geliştirebiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using ClientApp.ProductServicesRef;
namespace ClientApp
{
public partial class Form1 : Form
{
PhotoServiceClient proxy = null;
public Form1()
{
InitializeComponent();
proxy = new PhotoServiceClient();
}
private void btnGetProductList_Click(object sender, EventArgs e)
{
grdProducts.DataSource=proxy.GetProducts();
}
private void grdProducts_CellClick(object sender, DataGridViewCellEventArgs e)
{
int productId = Convert.ToInt32(grdProducts[2, e.RowIndex].Value);
byte[] byteArray= proxy.GetPhoto(productId);
using (MemoryStream stream = new MemoryStream(byteArray))
{
pcbImage.Image = Image.FromStream(stream);
}
}
}
}</pre>
<p>Kullanıcılar <strong>GetProductList</strong> düğmesini kullanarak servisten ürün listeni çekmektedir. Çekilen ürünler <strong>DataGridView</strong> kontrolüne aktarılmaktadır. Grid üzerinden herhangibir satıra tıklanıldığında ise seçilen ürünün ProductId değerine göre servisten resim bilgisi talep edilmektedir. Aşağıda çalışma zamanındaki örnek sonuçlardan birisi yer almaktadır.</p>
<p><img src="/pics/2009%2f6%2fblg34_6.gif" alt="" /></p>
<p>Burada hemen şu noktayı vurgulamak isterim. İstemci tarafına gönderilen <strong>byte</strong> dizisinin boyutu, yine istemci tarafındaki<strong> app.config</strong> dosyasında, <strong>readerQuotas</strong> elementi içerisindeki <strong>maxArrayLength</strong> özelliği ile sınırlandırılmıştır. Resimlerin boyutlarına göre bu değerin arttırılması gerekebilir ki benim örneğimde bu arttırım yapılmak zorunda kalınmıştır.<img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Nihayetinde ön hazırlıklarımız tamamlanmıştır. Artık servis tarafında kullanmak istediğimiz <strong>Caching Application Block</strong> ile ilişkili hazırlıklara başlayabiliriz. Öncelikle servis uygulamasına kullanılmak istenen Enterprise Library bloğu ile ilgili <strong>assembly</strong> referansının eklenmesi gerekmektedir.</p>
<p><img src="/pics/2009%2f6%2fblg34_7.gif" alt="" /></p>
<p>Böylece kod içerisinde, <strong>Caching Application Block</strong> ile ilişkili yönetimli kodlar ele alabileceğiz.<strong> Caching Application Block</strong>, ön belleğe alma işlemlerinde varsayılan olarak kullanıldığı host uygulamanın çalıştığı sistem belleğini ele almaktadır. Ancak istenirse saklama işlemleri için farklı bir kaynağın<em>(örneğin fiziki disk)</em> kullanılması sağlanabilir. Bunula birlikte, ön bellekte tutulacak maksimum eleman sayısınıda belirleyebiliriz. İyi ama bu ayarları nerede yapacağız? <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /> Tahmin edeceğiniz üzere host uygulamanın konfigurasyon dosyası içerisinde. Neyseki <strong>Enterprise Library</strong> kurulumlarından sonra, <strong>Visual Studio 2008</strong> için görsel bir arabirim gelmektedir. Böylece gerekli ayarları kolayca yapabiliriz.</p>
<p>İlk etapta servis uygulamasındaki <strong>web.config </strong>dosyasını<strong> Edit Enterprise Library Configuration</strong> ile açalım. <em>(İstenirse tüm ayarlamalar konfigurasyon dosyası içerisinden ellede yapılabilir.)</em></p>
<p><img src="/pics/2009%2f6%2fblg34_8.gif" alt="" /></p>
<p>Sonrasında ise <strong>Caching Application Block</strong> için gerekli <strong>XML</strong> sekmesini aşağıdaki şekildende görülebileceği gibi kolayca ilave edebiliriz.</p>
<p><img src="/pics/2009%2f6%2fblg34_9.gif" alt="" /></p>
<p>Bu işlemlerin ardından varsayılan olarak web.config dosyasının içeriği aşağıdaki gibi olacaktır.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><cachingConfiguration defaultCacheManager="Cache Manager">
<cacheManagers>
<add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="Cache Manager" />
</cacheManagers>
<backingStores>
<add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="Null Storage" />
</backingStores>
</cachingConfiguration></pre>
<p>Tabiki özellikler penceresindende pek çok ayarlama yapılabilir. Söz gelimi <strong>Protection Provider</strong> ile ön bellekte tutulacak nesnelerin şifrelenmesi için hangi sağlayıcının kullanılacağı belirlenebilir<em>(şu andaki örneğimizde herhangibir şifreleme sağlayıcısı kullanılmamaktadır)</em>. Peki bunlar yeterli midir? Elbetteki değildir. Ön bellekte kimi tutacağız? Ön bellekte tutmak istediğimiz nesne referansını nasıl ekleyecek veya nasıl çekeceğiz? Bu durumda <strong>GetPhoto</strong> metodunun içeriğini aşağıdaki gibi düzenlememiz yeterli olacaktır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public byte[] GetPhoto(int productId)
{
XDocument doc=XDocument.Load(ConfigurationManager.AppSettings["XmlSourcePath"]);
string imageFileName = (from p in doc.Element("Products").Elements("Product")
where p.Element("Id").Value == productId.ToString()
select p.Element("ImageFileName").Value).Single();
string imagePath = Path.Combine(ConfigurationManager.AppSettings["ImagesPath"], imageFileName);
byte[] imageBytes = null;
// İlk olarak çalışma zamanında, CacheManager referansı çekilir. Bu noktada fabrika tipinden yararlanılmaktadır.
ICacheManager cacheManager = CacheFactory.GetCacheManager();
// Eğer Cache koleksiyonunda, productId ile belirtilen bir referans tutulmuyorsa
if (cacheManager[productId.ToString()] == null)
{
imageBytes = File.ReadAllBytes(imagePath);
cacheManager.Add(productId.ToString(), imageBytes);
}
else // Eğer Cache koleksiyonunda productId anahtarına sahip bir referans var ise getir
imageBytes = (byte[])cacheManager[productId.ToString()];
return imageBytes;
}</pre>
<p>Peki sistem nasıl çalışmaktadır? <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /></p>
<p>İstemci bir ürün resmi talep ettiğinde, kod parçasına göre öncelikle ön bellekte olup olmadığına bakılır. Eğer ön bellekte <span style="text-decoration: underline;">değilse</span> <strong>Add</strong> metodu yardımıyla ön belleğe ekleme işlemi yapılır. Eğer nesne ön bellekte ise, <strong>indeksleyiciden</strong> yararlanılarak resmin <strong>byte[]</strong> dizisine <strong>cast</strong> edilerek elde edilmesi sağlanır. Burada önemli olan noktalardan biriside şudur; servise ait host uygulama açık olduğu sürece <strong>productId</strong> bazlı resimler ön bellekte saklanmaya ve korunmaya devam edecektir. Ancak host uygulamanın kapatılması durumunda, ön bellek koleksiyonuda otomatik olarak temizlenmektedir. Diğer yandan ön bellekte tutulan nesnelerin tamamını bilinçli bir şekilde temizlemek istersek, <strong>ICacheManager</strong> referansı üzerinden <strong>Flush</strong> metodunun çağırılması yeterli olacaktır. Yazımı sonlandırmadan önce son olarak şu noktayada değinmek isterim; senaryomuzda <strong>Caching</strong> bloğunu sunucu tarafındaki servis uygulaması için ele almış bulunmaktayız.</p>
<p>Buna göre istemci aynı resimleri talep ettiği ve servis uygulamasıda ayakta olduğu sürece, resimler ön bellekten tedarik edilecektir. Bu işlem resmin istemciye hızlı bir şekilde iletilmesini sağlamak üzere yapılmamıştır. Buna lütfen dikkat edelim. Aksine servis tarafındaki gereksiz resim okuma işlemini ekarte etmek amacıyla kullanılmıştır(Bu bloğun başka ne tip senaryolarda kullanılabileceğini düşünmenizi tavsiye ederim) Senaryomuzda elbetteki eksik kısımlar mevcuttur. Örneğin istisna yönetimi(Exception Handling) sıfırdır. <img title="Embarassed" src="/editors/tiny_mce3/plugins/emotions/img/smiley-embarassed.gif" alt="Embarassed" border="0" /> Asenkron erişim ile ilişkili istemci tarafında hiç bir şey yapılmamıştır. <img title="Sealed" src="/editors/tiny_mce3/plugins/emotions/img/smiley-sealed.gif" alt="Sealed" border="0" /> Diğer yandan <span style="text-decoration: underline;">resmin değişmesi</span> halinde cache içeriğinin güncellenmesi ile ilgili bir çalışmada yapılmamıştır ki yapmaya çalışmanızı öneririm. <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /></p>
<p>Şimdilik benden bu kadar. Yeni bir western filmi sonrasında tekrardan <strong>Enterprise Library</strong> konulu bir örnek ile görüşmek üzere...</p>
<p><a href="https://buraksenyurt.com/pics/2009%2f6%2fHelloCachingBlock.rar">HelloCachingBlock.rar (5,35 mb)</a></p>2009-06-20T17:52:00+00:00enterprise librarywcfbsenyurtAz önce 1966 yılında çevrilmiş olan ve küçüklüğümde bol bol izlediğim nefis bir filmi belkide 179ncu kez tekrardan seyrettim. Eskiler aşağıdaki resimden hangi film olabileceğini tahmin edebilirler. Yeni nesilden seyretmeyen varsa eğer The Good, The Bad and The Ugly filmini mutlaka tedarik edip izlesinler. Peki bunun anlatacağım konu ile bir ilgisi var mı? Hayır yok. Cool Sadece off-topic bir giriş yapmak istedim.https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=9412d6b7-757a-4a45-8136-dc8f830708bc0https://buraksenyurt.com/trackback.axd?id=9412d6b7-757a-4a45-8136-dc8f830708bchttps://buraksenyurt.com/post/Caching-Application-Block-Merakc4b1#commenthttps://buraksenyurt.com/syndication.axd?post=9412d6b7-757a-4a45-8136-dc8f830708bc