İşte Jon Davis'in makalesi. Okunabilirliği korumak için, artık kullanılmayan EntLib bölümünü, girişi ve sonucu kesiyorum.
ASP.NET Önbelleği
ASP.NET veya System.Web.dll derlemesinin bir önbelleğe alma mekanizması vardır. Asla bir web bağlamının dışında kullanılması amaçlanmamıştır, ancak web dışında kullanılabilir ve yukarıdaki tüm sona erme davranışlarını bir tür hashtable içinde gerçekleştirir.
Google'ı araştırdıktan sonra, .NET'teki yerleşik önbelleğe alma işlevini tartışan pek çok kişinin web dışı projelerinde ASP.NET önbelleğini kullanmaya başvurduğu görülüyor. Bu artık .NET'te en çok bulunan, en çok desteklenen yerleşik önbelleğe alma sistemi değildir; .NET 4'te daha sonra gireceğim bir ObjectCache var. Microsoft, ASP.NET önbelleğinin web dışında kullanılmak üzere tasarlanmadığı konusunda her zaman kararlı olmuştur. Ancak birçok kişi hala .NET 2.0 ve .NET 3.5'te sıkışmış durumda ve üzerinde çalışacak bir şeye ihtiyaç duyuyor ve MSDN açıkça şunu söylese de bu birçok kişi için işe yarıyor:
Not: Cache sınıfı, ASP.NET uygulamalarının dışında kullanılmak üzere tasarlanmamıştır. Web uygulamaları için önbelleğe alma sağlamak için ASP.NET'te kullanılmak üzere tasarlanmış ve test edilmiştir. Konsol uygulamaları veya Windows Forms uygulamaları gibi diğer türden uygulamalarda, ASP.NET önbelleğe alma düzgün çalışmayabilir.
ASP.NET önbelleğinin sınıfı, System.Web.dll'deki System.Web.Caching.Cache'dir. Ancak, bir Cache nesnesini basitçe yenileyemezsiniz. Bunu System.Web.HttpRuntime.Cache'den edinmelisiniz.
Cache cache = System.Web.HttpRuntime.Cache;
ASP.NET önbelleğiyle çalışma, burada MSDN'de belgelenmiştir .
Artıları:
- Bu oluyor yerleşik .
- .NET 1.0 sözdizimine rağmen, kullanımı oldukça basittir .
- Web bağlamında kullanıldığında, iyi test edilmiştir . Web bağlamları dışında, Google aramalarına göre, Microsoft'un aleyhine önermesine rağmen, .NET 2.0 veya sonraki bir sürümünü kullandığınız sürece sorunlara neden olduğu yaygın olarak bilinmemektedir.
- Sen edilebilir bildirilir hayatta tutmak gerekiyor ve önceden öğesinin önceliğini ayarlamak olamazdı eğer gerekli bir öğe kaldırılır Bir temsilci aracılığıyla.
- Tek tek öğeler , bu makalenin başındaki kaldırma yöntemleri listesinde yer alan (a), (b) veya (c) son kullanma ve kaldırma yöntemlerinden herhangi birinin esnekliğine sahiptir. Ayrıca sona erme davranışını fiziksel bir dosyanın varlığı ile ilişkilendirebilirsiniz.
Eksileri:
- Sadece durağan değil, sadece bir tane var . Kendi statik önbellek örneğiyle kendi türünüzü oluşturamazsınız. Tüm uygulamanız için yalnızca bir gruba sahip olabilirsiniz. Kovayı, anahtarlarda ön eklerin eklenmesi gibi şeyler yapan kendi sarmalayıcılarınızla sarabilir ve anahtar / değer çiftlerini geri çektiğinizde bu önekleri kaldırabilirsiniz. Ama hala tek bir kova var. Her şey bir araya toplanmış. Örneğin, üç veya dört farklı türde veriyi ayrı ayrı önbelleğe alması gereken bir hizmetiniz varsa, bu gerçek bir sıkıntı olabilir. Acınacak kadar basit projeler için bu büyük bir sorun olmamalı. Ancak, bir projenin gereksinimleri nedeniyle herhangi bir önemli düzeyde karmaşıklığı varsa, ASP.NET önbelleği genellikle yeterli olmaz.
- Öğeler ister istemez kaybolabilir. Pek çok insan bunun farkında değil - bu önbellek uygulaması hakkındaki bilgilerimi tazeleyene kadar farkında değildim. Varsayılan olarak, ASP.NET önbelleği, kendisi gibi "hissettiğinde" öğeleri yok etmek için tasarlanmıştır. Daha spesifik olarak, bu makalenin başındaki önbellek tablosu tanımımda (c) kısmına bakın. Aynı süreçteki başka bir iş parçacığı tamamen farklı bir şey üzerinde çalışıyorsa ve yüksek öncelikli öğeleri önbelleğe atıyorsa, o zaman .NET biraz belleğe ihtiyaç duyması gerektiğine karar verir vermez önbellekteki bazı öğeleri, öncelikleri, önce daha düşük öncelikler. Önbellek öğeleri eklemek için burada belgelenen tüm örnekler, bellek temizleme amacıyla kaldırılmasını engelleyen NotRemovable öncelik değeri yerine varsayılan önceliği kullanır, ancak yine de süre sonu ilkesine göre kaldırır.
- Anahtar bir dizge olmalıdır. Örneğin, kayıtların uzun veya tam sayıya dayalı olduğu veri kayıtlarını önbelleğe alıyorsanız, önce anahtarı bir dizeye dönüştürmeniz gerekir.
- Sözdizimi bayat . ArrayList veya Hashtable'dan bile daha çirkin olan .NET 1.0 sözdizimidir. Burada jenerik yok, IDictionary <> arayüzü yok. Contains () yöntemi yoktur, Anahtar koleksiyonu yoktur, standart olay yoktur; yalnızca bir Get () yöntemine ve Get () ile aynı şeyi yapan, eşleşme yoksa boş döndüren bir dizinleyiciye ve ayrıca Add (), Insert () (fazlalık?), Remove () ve GetEnumerator () .
- Varsayılan sona erme / kaldırma davranışlarınızı kurmaya yönelik KURU ilkesini yok sayar, böylece bunları unutabilirsiniz. Önbelleğe, her öğe eklediğinizde eklediğiniz öğenin süresinin nasıl dolmasını veya kaldırılmasını istediğinizi açıkça belirtmeniz gerekir.
- Önbelleğe alınan bir öğenin, eklendiği zamanın zaman damgası gibi önbelleğe alma ayrıntılarına erişmenin bir yolu yoktur . Kapsülleme burada biraz abartıldı ve önbelleğe alınmış bir öğenin başka bir önbelleğe alma mekanizmasına (yani oturum toplama) karşı geçersiz kılınması gerekip gerekmediğini belirlemeye çalışırken kodda önbelleği kullanmayı zorlaştırdı.
- Kaldırma olayları , olay olarak gösterilmez ve eklenme sırasında izlenmelidir.
- Ve yeterince söylemediysem, Microsoft açık bir şekilde web dışında buna karşı öneride bulunuyor . Ve eğer .NET 1.1 ile lanetlendiyseniz , onu web dışında herhangi bir kararlılıkla kullanmamalısınız, bu yüzden zahmet etmeyin.
.NET 4.0'ın ObjectCache / MemoryCache
Microsoft nihayet .NET Framework'ün en son sürümünde soyut bir ObjectCache sınıfı ve web dışı bir ortamda bellek içi amaçlar için ObjectCache'yi devralan ve uygulayan bir MemoryCache uygulaması gerçekleştirdi.
System.Runtime.Caching.ObjectCache, System.Runtime.Caching.dll derlemesindedir. ASP.NET önbelleğinde bulunan temelde aynı .NET 1.0 stili arabirimlerini bildiren soyut bir sınıftır. System.Runtime.Caching.MemoryCache
ObjectCache'nin bellek içi uygulamasıdır ve birkaç değişiklikle ASP.NET önbelleğine çok benzer.
Kayan bir son kullanma tarihine sahip bir öğe eklemek için kodunuz aşağıdaki gibi görünecektir:
var config = new NameValueCollection();
var cache = new MemoryCache("myMemCache", config);
cache.Add(new CacheItem("a", "b"),
new CacheItemPolicy
{
Priority = CacheItemPriority.NotRemovable,
SlidingExpiration=TimeSpan.FromMinutes(30)
});
Artıları:
- Yerleşiktir ve artık Microsoft tarafından web dışında desteklenmekte ve önerilmektedir.
ASP.NET önbelleğinden farklı olarak, bir MemoryCache nesnesi örneğini başlatabilirsiniz.
Not: Statik olması gerekmez, ancak olması gerekir — bu Microsoft'un önerisidir (bkz. Sarı Dikkat) .
Öğeler eklendiğinde, gereksiz Insert () kaldırıldığında, öğeler bir CacheItem ile eklenebilirken, kaldırma olaylarına abone olma yeteneği gibi ASP.NET önbelleğinin arabirimine göre birkaç küçük iyileştirme yapılmıştır. önbelleğe alma stratejisini tanımlayan bir başlatıcıya sahip nesne ve İçerir () eklendi.
Eksileri:
- Yine de KURU'yu tam olarak güçlendirmiyor. Benim küçük deneyimlerime göre, kayan süre sonu TimeSpan'ı bir kez ayarlayıp unutamazsınız. Ve açıkçası, yukarıdaki öğe ekleme örneğindeki politika daha okunaklı olsa da, korkunç ayrıntılar gerektiriyor.
- Halen jenerik olarak anahtarlanmamıştır; anahtar olarak bir dizge gerektirir. Dolayısıyla, dizeye dönüştürmediğiniz sürece veri kayıtlarını önbelleğe alıyorsanız, uzun veya int depolayamazsınız.
Kendin Yap: Kendin Yap
Açık veya kayan süre sonu gerçekleştiren bir önbelleğe alma sözlüğü oluşturmak aslında oldukça basittir. (Bellek temizleme amacıyla öğelerin otomatik olarak kaldırılmasını istiyorsanız, çok daha zor hale gelir.) Yapmanız gereken tek şey:
- T türü bir değer içerecek Expiring veya Expirable gibi bir şey, değer önbelleğe eklendiğinde saklanacak DateTime türünde bir TimeStamp özelliği ve zaman damgasından ne kadar uzakta olduğunu gösteren bir TimeSpan oluşturun. öğenin süresi dolmalıdır. Açık bir süre sonu için, zaman damgası tarafından çıkarılan bir tarihe verilen TimeSpan'ı ayarlayan bir özellik ayarlayıcısını açığa çıkarabilirsiniz.
- Bir sınıf oluşturun, buna IDictionary uygulayan ExpirableItemsDictionary diyelim. Tüketici tarafından tanımlanan genel bir sınıf yapmayı tercih ediyorum.
- # 2'de oluşturulan sınıfta, özellik olarak Dictionary> ekleyin ve InnerDictionary olarak adlandırın.
- # 2'de oluşturulan sınıftaki if IDictionary uygulaması, önbelleğe alınmış öğeleri depolamak için InnerDictionary kullanmalıdır. Kapsülleme, yukarıda # 1'de oluşturulan türün örnekleri aracılığıyla önbelleğe alma yöntemi ayrıntılarını gizler.
- Dizin oluşturucunun (bu []), ContainsKey (), vb., Bir değeri döndürmeden önce süresi dolmuş öğeleri temizlemeye ve süresi dolmuş öğeleri kaldırmaya dikkat edin. Öğe kaldırılmışsa alıcılarda null döndür.
- Tüm alıcılar, ayarlayıcılar, ContainsKey () ve özellikle son kullanma tarihi geçmiş öğeleri temizlerken iş parçacığı kilitlerini kullanın.
- Son kullanma tarihi nedeniyle bir öğe kaldırıldığında bir etkinlik oluşturun.
- Bir System.Threading.Timer örneği ekleyin ve süresi dolan öğeleri her 15 saniyede bir otomatik olarak kaldırmak için başlatma sırasında donatın. Bu, ASP.NET önbelleğiyle aynı davranıştır.
- Zaten varsa, öğenin kapsayıcısındaki (Süresi dolan örnek) zaman damgasını değiştirerek kayan sona erme süresini dışarı iten bir AddOrUpdate () rutini eklemek isteyebilirsiniz.
Microsoft orijinal tasarımlarını desteklemek zorundadır çünkü kullanıcı tabanı bunlara bağımlıdır, ancak bu onların iyi tasarımlar oldukları anlamına gelmez.
Artıları:
- Uygulama üzerinde tam kontrole sahipsiniz .
- Can KURUTMA pekiştirmek varsayılan önbelleğe alma davranışları kurma ve sonra sadece önbelleğe alma bildirmek olmadan anahtar / değer çiftlerini bırakarak Öğe eklemek her zaman detayları.
- Yani modern arayüzler uygulayabilir
IDictionary<K,T>
. Bu, arayüzü bir sözlük arayüzü olarak daha öngörülebilir olduğu için tüketmeyi çok daha kolay hale getirir ve ayrıca, IDictionary <> ile çalışan yardımcılar ve genişletme yöntemleri için daha erişilebilir hale getirir.
- Önbelleğe alma ayrıntıları , örneğin InnerDictionary'nizi salt okunur bir özellik aracılığıyla açığa çıkararak, önbelleğe alma stratejinize göre açık birim testleri yazmanıza ve temel önbelleğe alma uygulamanızı, üzerine inşa edilen ek önbelleğe alma stratejileriyle genişletmenize olanak sağlayarak, kapsüllenmemiş olabilir .
- Kendilerini ASP.NET önbelleğinin .NET 1.0 tarzı sözdizimi veya Önbelleğe Alma Uygulama Bloğu ile zaten rahat hissedenler için tanıdık bir arabirim olmasa da, arabirimi istediğiniz gibi görünecek şekilde tanımlayabilirsiniz .
- Anahtarlar için herhangi bir türü kullanabilir. Jenerik ilaçların yaratılmasının bir nedeni budur. Her şey bir dizeyle anahtarlanmamalıdır.
Eksileri:
- Microsoft tarafından icat edilmediği ve desteklenmediği için aynı kalite güvencesine sahip olmayacak.
- Yalnızca yukarıda anlattığım talimatların uygulandığını varsayarsak, öncelik temelinde belleği temizlemek için öğeleri "ister istemez" temizlemiyor (bu, yine de bir önbelleğin köşe durum yardımcı program işlevidir .. Önbelleği kullanacağınız yerde RAM SATIN ALIN , RAM ucuzdur).
Bu dört seçenek arasında tercihim bu. Bu temel önbelleğe alma çözümünü uyguladım. Şimdiye kadar mükemmel çalışıyor gibi görünüyor, bilinen bir hata yok (lütfen aşağıdaki yorumlarla bana ulaşın veya varsa jon-at-jondavis'den iletişime geçin !!) ve bunu ihtiyaç duyan tüm küçük yan projelerimde kullanmayı düşünüyorum temel önbelleğe alma. İşte burada:
Github bağlantısı: https://github.com/kroimon/ExpirableItemDictionary
Eski Bağlantı: ExpirableItemDictionary.zip
Bahsetmeye Değer: AppFabric, NoSQL, Et Al
Bu blog makalesinin başlığının "Ağır Hizmet Önbelleğe Alma" yerine "Basit Önbelleğe Alma" anlamına geldiğine dikkat edin. Ağır hizmet işlerine girmek istiyorsanız, özel, ölçeklenebilir çözümlere bakmalısınız.