|
|
Veröffentlicht am 19.04.2015 22:06:12
|
|
|
|

ASP.NET Ausgabe-Caching (d. h. statisches HTML) war bis zu .NET 4.0 speicherbasiert. Das bedeutet, wenn unsere Seite viel Cache enthält, ist es einfach, lokalen Speicher zu verbrauchen. Jetzt, mit Hilfe von . OutputCacheProvider in .NET 4.0, wir haben mehrere Möglichkeiten, unseren eigenen Cache zu erstellen. Zum Beispiel können wir den HTML-Ausgabe-Cache in einem memcached verteilten Cluster-Server oder in MongoDB speichern (eine häufig verwendete dokumentorientierte Datenbank, lesen Sie dies http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Natürlich können wir den Cache auch als Datei auf der Festplatte speichern, was unter Berücksichtigung der Skalierbarkeit der günstigste Weg ist, und dieser Artikel behandelt, wie man einen benutzerdefinierten Dateicache erstellt.
1:OutputCacheProvider OutputCacheProvider ist eine abstrakte Basisklasse, bei der wir vier ihrer Methoden überschreiben müssen, nämlich: Fügen Sie die Methode hinzu, um das angegebene Element in den Ausgabe-Cache einzufügen. Get-Methode, die eine Referenz auf das angegebene Element im Ausgabecache zurückgibt. Remove Methode, um das angegebene Element aus dem Ausgabe-Cache zu entfernen. set-Methode, fügt das angegebene Element in den Ausgabecache ein und überschreibt das Element, falls es zwischengespeichert ist.
2: Erstellen Sie Ihre eigene Datei-Caching-Verarbeitungsklasse Der Typ ist FileCacheProvider, und der Code lautet wie folgt:
- 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;
- }
- }
Code kopieren Es gibt zwei Bereiche, die besondere Aufmerksamkeit benötigen: In der Add-Methode gibt es ein bedingtes Urteil, das auf diese Weise behandelt werden muss, andernfalls speichert der Caching-Mechanismus das erste Ergebnis und der Cache verfällt nach dem Ablaufdatum und wird nicht wieder aufgebaut. Im Beispielprogramm legen wir den Cache einfach ins Cache-Verzeichnis, und in der tatsächlichen Projektpraxis, da die zwischengespeicherten Seiten tausend sind, müssen wir eine Verzeichnisklassifikation durchführen, sonst wird das Finden und Lesen von Cache-Dateien zu einem Effizienz-Engpass, der die CPU erschöpft.
3: Konfigurationsdatei
Wir müssen in Web.config so konfigurieren, dass der Cache-Handler ein benutzerdefinierter FileCacheProvider ist, also einen Knoten unter FileCacheProvider hinzufügen:- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Code kopieren
4: Nutzung des Caches
Wir gehen davon aus, dass die Nutzung in MVC's Control (wenn Sie es auf einer ASP.NET Seite verwenden möchten, fügen Sie <% in die page@OutputCache VaryByParam="none" Duration="10" %>) an, und Sie sehen können, dass Index nicht zwischengespeichert wird, während Index2 für 10 Sekunden ausgegeben wird.
- 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();
- }
- }
Code kopieren 5: Überprüfen Sie den Effekt Der obige Code erzeugt nach dem Zugriff auf Index2 eine Cache-Datei im Cache-Ordner wie folgt:
Nun evaluieren wir den Leistungsvergleich zwischen dem Output-Cache und dem Output-Cache und simulieren 100 gleichzeitige Anfragen von 100 Nutzern wie folgt:
|
Vorhergehend:Lebenszyklus der SitzungNächster:C#. .NET, um SQL-Injektionsangriffe zu verhindern
|