ASP.NET cache di output (cioè HTML statico) era basata sulla memoria fino a .NET 4.0. Questo significa che se il nostro sito contiene molta cache, è facile consumare memoria locale. Ora, con l'aiuto di . OutputCacheProvider in .NET 4.0, abbiamo diverse opzioni per creare la nostra cache. Ad esempio, possiamo memorizzare la cache di uscita HTML in un server cluster distribuito con memcache o in MongoDB (un database orientato ai documenti comunemente usato, leggi http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Ovviamente, possiamo anche memorizzare la cache come file sull'hard disk, che è il modo più economico considerando la scalabilità, e questo articolo parla di come costruire una cache file personalizzata.
1:OutputCacheProvider OutputCacheProvider è una classe base astratta per cui dobbiamo sovrascrivere quattro dei suoi metodi, che sono: Aggiungi il metodo per inserire l'elemento specificato nella cache di output. get, che restituisce un riferimento all'elemento specificato nella cache di output. Rimuovi il metodo per rimuovere l'elemento specificato dalla cache di output. imposta, inserisce l'elemento specificato nella cache di output e sovrascrive l'elemento se è archiviato.
2: Crea la tua classe di gestione della cache file Il tipo è FileCacheProvider, e il codice è il seguente:
- 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;
- }
- }
Copia codice Ci sono due luoghi che richiedono particolare attenzione: Nel metodo Aggiungi, esiste un giudizio condizionale che deve essere gestito in questo modo, altrimenti il meccanismo di cache memorizzerà il primo risultato, la cache scadrà dopo la data di scadenza e non verrà ricostruita. Nel programma di esempio, mettiamo semplicemente la cache nella directory della cache, e nella pratica reale del progetto, considerando che le pagine cache saranno migliaia, dobbiamo fare la classificazione delle directory, altrimenti trovare e leggere file cache diventerebbe un collo di bottiglia di efficienza, che consumerà la CPU.
3: File di configurazione
Dobbiamo configurare in Web.config che il gestore della cache sia un FileCacheProvider personalizzato, cioè aggiungere un nodo sotto FileCacheProvider:- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Copia codice
4: Uso della cache
Supponiamo che l'uso sotto il controllo di MVC (se vuoi usarlo in una pagina ASP.NET, includi il <% nella page@OutputCache VaryByParam="none" Duration="10" %>), e puoi vedere che Index non è in cache in output, mentre Index2 è in cache per 10 secondi.
- 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();
- }
- }
Copia codice 5: Controlla l'effetto Il codice sopra, dopo aver consultato Index2, genererà un file cache nella cartella Cache, come segue:
Ora, valutiamo il confronto delle prestazioni tra la cache di uscita e quella di output, simulando 100 richieste concorrenti da 100 utenti come segue:
|