ASP.NET output-caching (dvs. statisk HTML) var hukommelsesbaseret indtil .NET 4.0. Det betyder, at hvis vores site indeholder meget cache, er det nemt at bruge lokal hukommelse. Nu, med hjælp fra . OutputCacheProvider i .NET 4.0 har vi flere muligheder for at oprette vores egen cache. For eksempel kan vi gemme HTML-outputcachen i en memcachet distribueret klyngeserver eller MongoDB (en almindeligt brugt dokumentorienteret database, læs dette http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Selvfølgelig kan vi også gemme cachen som en fil på harddisken, hvilket er den billigste måde at gøre det på med hensyn til skalerbarhed, og denne artikel handler om, hvordan man bygger en brugerdefineret filcache.
1:OutputCacheProvider OutputCacheProvider er en abstrakt baseklasse, som vi skal tilsidesætte fire af dens metoder, som er: Tilføj metode til at indsætte det specificerede element i output-cachen. Get-metoden, som returnerer en reference til det angivne element i outputcachen. Fjern metode for at fjerne det specificerede element fra outputcachen. Set metode, indsætter det specificerede element i outputcachen og overskriver elementet, hvis det er cachet.
2: Opret din egen fil-caching håndteringsklasse Typen er FileCacheProvider, og koden er som følger:
- 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;
- }
- }
Kopier kode Der er to steder, der kræver særlig opmærksomhed: I Add-metoden er der en betinget vurdering, der skal håndteres på denne måde, ellers vil caching-mekanismen cache det første resultat, og cachen udløber efter udløbsdatoen og vil ikke blive genopbygget. I eksempelprogrammet lægger vi blot cachen i cache-mappen, og i faktisk projektpraksis, når vi tager i betragtning at de cachede sider vil være tusindvis, skal vi lave mappeklassifikation, ellers vil det at finde og læse cachefiler blive en effektivitetsflaskehals, som dræner CPU'en.
3: Konfigurationsfil
Vi skal konfigurere i Web.config, så cache-handleren er en brugerdefineret FileCacheProvider, dvs. tilføje en node under FileCacheProvider:- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Kopier kode
4: Brug af cache
Vi antager, at brug af det i MVC's kontrol (hvis du vil bruge det på en ASP.NET-side, inkluder <% i page@OutputCache VaryByParam="ingen" Varighed="10" %>), og du kan se, at Index ikke outputtes cachet, mens Index2 er outputtet cachet i 10 sekunder.
- 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();
- }
- }
Kopier kode 5: Tjek effekten Ovenstående kode vil efter tilgang til Index2 generere en cachefil i cache-mappen som følger:
Lad os nu evaluere performance-sammenligningen mellem outputcachen og outputcachen og simulere 100 samtidige forespørgsler fra 100 brugere som følger:
|