ASP.NET cache de ieșire (adică HTML static) era bazată pe memorie până la .NET 4.0. Asta înseamnă că, dacă site-ul nostru conține mult cache, este ușor să consumi memorie locală. Acum, cu ajutorul lui . OutputCacheProvider în .NET 4.0, avem mai multe opțiuni pentru a crea propriul nostru cache. De exemplu, putem stoca cache-ul de ieșire HTML într-un server cluster distribuit cu memcaching sau într-un MongoDB (o bază de date orientată pe documente folosită frecvent, citiți acest http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Desigur, putem stoca și cache-ul ca fișier pe hard disk, ceea ce este cea mai ieftină metodă având în vedere scalabilitatea, iar acest articol este despre cum să construiești un cache de fișiere personalizat.
1:OutputCacheProvider OutputCacheProvider este o clasă de bază abstractă pe care trebuie să o suprascriem pentru patru dintre metodele sale, care sunt: Adaugă metoda pentru a introduce elementul specificat în cache-ul de ieșire. Get, care returnează o referință la elementul specificat din cache-ul de ieșire. Metoda de eliminare pentru a elimina elementul specificat din cache-ul de ieșire. set, introduce elementul specificat în cache-ul de ieșire și suprascrie elementul dacă este stocat în cache.
2: Creează-ți propria clasă de gestionare a cache-ului fișierelor Tipul este FileCacheProvider, iar codul este următorul:
- 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;
- }
- }
Cod de copiere Există două locuri care necesită atenție specială: În metoda Adunării, există o judecată condiționată care trebuie gestionată în acest mod, altfel mecanismul de cache va stoca primul rezultat, iar cache-ul va expira după data expirării și nu va fi reconstruit. În programul exemplu, pur și simplu punem cache-ul în directorul cache, iar în practica reală a proiectului, având în vedere că paginile stocate în cache vor fi mii, trebuie să facem clasificarea directoarelor, altfel găsirea și citirea fișierelor cache va deveni un blocaj de eficiență, ceea ce va consuma CPU-ul.
3: Fișier de configurare
Trebuie să configurăm în Web.config ca handler-ul de cache să fie un FileCacheProvider personalizat, adică să adăugăm un nod sub FileCacheProvider:- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Cod de copiere
4: Utilizarea cache-ului
Presupunem că folosindu-l sub controlul MVC (dacă vrei să-l folosești pe o pagină de ASP.NET, include <% în page@OutputCache VaryByParam="none" Duration="10" %>), și poți vedea că Index nu este stocat în cache de ieșire, în timp ce Index2 este stocat în cache timp de 10 secunde.
- 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();
- }
- }
Cod de copiere 5: Verifică efectul Codul de mai sus, după ce accesează Index2, va genera un fișier cache în folderul Cache, după cum urmează:
Acum, să evaluăm comparația de performanță dintre cache-ul de ieșire și cache-ul de ieșire, simulând 100 de cereri concurente de la 100 de utilizatori după cum urmează:
|