ASP.NET çıktı önbellekleme (yani statik HTML) .NET 4.0'a kadar bellek tabanlıydı. Bu, sitemizde çok fazla önbellek varsa, yerel belleği kolayca tüketebileceği anlamına gelir. Şimdi, . .NET 4.0'da OutputCacheProvider ile kendi önbelleğimizi oluşturmak için birkaç seçeneğimiz var. Örneğin, HTML çıktı önbelleğini memcache dağılık dağıtılmış küme sunucusunda veya MongoDB'de (yaygın kullanılan bir belge odaklı veritabanı, bu http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx okuyun) depolayabiliriz. Elbette, önbelleği sabit diskte dosya olarak da saklayabiliriz; ölçeklenebilirlik göz önüne alındığında bu en ucuz yöntemdir ve bu makale özel bir dosya önbelleği nasıl oluşturulurla ilgilidir.
1:OutputCacheProvider OutputCacheProvider, dört yöntemini geçersiz kılmamız gereken soyut bir temel sınıftır; bunlar şunlardır: Belirtilen öğeyi çıktı önbelleğine eklemek için yöntem ekleyin. Get metodu ile çıktı önbelleğinde belirtilen öğeye referans döndürür. Belirtilen öğeyi çıktı önbelleğinden çıkarmak için yöntemi kaldırın. Set metodu, belirtilen öğeyi çıktı önbelleğe ekler ve önbellekliyse öğenin üzerine yazar.
2: Kendi dosya önbellekleme işleme sınıfınızı oluşturun Tip FileCacheProvider'dır ve kod şu şekildedir:
- public class FileCacheProvider : OutputCacheProvider
- {
- private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
-
- public override void Initialize(string name, NameValueCollection attributes)
- {
- base.Initialize(name, attributes);
- CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]);
- }
-
- public override object Add(string key, object entry, DateTime utcExpiry)
- {
- Object obj = Get(key);
- if (obj != null) //这一步很重要
- {
- return obj;
- }
- Set(key,entry,utcExpiry);
- return entry;
- }
-
- public override object Get(string key)
- {
- string path = ConvertKeyToPath(key);
- if (!File.Exists(path))
- {
- return null;
- }
- CacheItem item = null;
- using (FileStream file = File.OpenRead(path))
- {
- var formatter = new BinaryFormatter();
- item = (CacheItem)formatter.Deserialize(file);
- }
-
- if (item.ExpiryDate <= DateTime.Now.ToUniversalTime())
- {
- log.Info(item.ExpiryDate + "*" + key);
- Remove(key);
- return null;
- }
- return item.Item;
- }
-
-
- public override void Set(string key, object entry, DateTime utcExpiry)
- {
- CacheItem item = new CacheItem(entry, utcExpiry);
- string path = ConvertKeyToPath(key);
- using (FileStream file = File.OpenWrite(path))
- {
- BinaryFormatter formatter = new BinaryFormatter();
- formatter.Serialize(file, item);
- }
- }
-
- public override void Remove(string key)
- {
- string path = ConvertKeyToPath(key);
- if (File.Exists(path))
- File.Delete(path);
- }
-
- public string CachePath
- {
- get;
- set;
- }
-
- private string ConvertKeyToPath(string key)
- {
- string file = key.Replace('/', '-');
- file += ".txt";
- return Path.Combine(CachePath, file);
- }
- }
-
- [Serializable]
- public class CacheItem
- {
- public DateTime ExpiryDate;
- public object Item;
-
- public CacheItem(object entry, DateTime utcExpiry)
- {
- Item = entry;
- ExpiryDate = utcExpiry;
- }
- }
Kopya kodu Özel dikkat gerektiren iki yer vardır: Ekle yönteminde, bu şekilde ele alınması gereken koşullu bir karar vardır; aksi takdirde önbellek mekanizması ilk sonucu önbelleyecek ve önbellek son kullanma tarihinden sonra sona erer ve yeniden inşa edilmez. Örnek programda, önbelleği önbellek dizinine koyuyoruz ve gerçek proje uygulamasında, önbelleğe alınan sayfaların binlerce olacağı göz önüne alındığında, dizin sınıflandırması yapmak zorundayız, aksi takdirde önbellek dosyalarını bulmak ve okumak verimlilik darboğazı haline gelir ve CPU'yu tüketir.
3: Yapılandırma dosyası
Web.config'de önbellek işleyicisinin özel bir FileCacheProvider olduğunu yapılandırmamız gerekiyor, yani FileCacheProvider altına bir düğüm eklemek gerekir:- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Kopya kodu
4: Önbellek kullanımı
MVC'nin kontrolünde kullanıldığında (ASP.NET sayfasında kullanmak istiyorsanız, page@OutputCache VaryByParam="none" Duration="10" %> içine %<% ekleyin) ve Index'in çıktı önbelleğe alınmadığını, Index2'nin ise 10 saniye önbelleğe alındığını görebilirsiniz.
- public class HomeController : Controller
- {
- private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- static string s_conn = "Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;";
- public ActionResult Index()
- {
- using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
- {
- ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
- }
- return View();
- }
-
- [OutputCache(Duration = 10, VaryByParam = "none")]
- public ActionResult Index2()
- {
- using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
- {
- ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
- }
- return View();
- }
- }
Kopya kodu 5: Etkisini kontrol et Yukarıdaki kod, Index2'ye erişildikten sonra, Cache klasöründe aşağıdaki gibi bir önbellek dosyası oluşturur:
Şimdi, çıkış önbelleği ile çıktı önbelleği arasındaki performans karşılaştırmasını değerlendirelim ve 100 kullanıcıdan gelen 100 eşzamanlı talebi şu şekilde simüle edelim:
|