ASP.NET cache de sortie (c’est-à-dire HTML statique) était basée sur la mémoire jusqu’à .NET 4.0. Cela signifie que si notre site contient beaucoup de cache, il est facile de consommer de la mémoire locale. Maintenant, avec l’aide de . OutputCacheProvider dans .NET 4.0, nous avons plusieurs options pour créer notre propre cache. Par exemple, nous pouvons stocker le cache de sortie HTML dans un serveur cluster distribué à caches memcachées ou MongoDB (une base de données orientée document couramment utilisée, lisez ceci http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Bien sûr, nous pouvons aussi stocker le cache sous forme de fichier sur le disque dur, ce qui est la méthode la moins coûteuse compte tenu de la scalabilité, et cet article porte sur la façon de construire un cache de fichiers personnalisé.
1 :FournissCacheSortie OutputCacheProvider est une classe de base abstraite dont nous devons outrepasser quatre de ses méthodes, à savoir : Méthode Add pour insérer l’élément spécifié dans le cache de sortie. Get, qui renvoie une référence à l’élément spécifié dans le cache de sortie. Méthode de suppression pour retirer l’élément spécifié du cache de sortie. set, insère l’élément spécifié dans le cache de sortie, et écrase l’élément s’il est mis en cache.
2 : Créez votre propre classe de gestion de la cache de fichiers Le type est FileCacheProvider, et le code est le suivant :
- 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 de copie Il y a deux endroits qui nécessitent une attention particulière : Dans la méthode Addition, il y a un jugement conditionnel qui doit être géré de cette manière, sinon le mécanisme de mise en cache mettra en cache le premier résultat, et le cache expirera après la date d’expiration et ne sera pas reconstruit. Dans le programme d’exemple, nous mettons simplement le cache dans le répertoire du cache, et en pratique réelle du projet, étant donné que les pages mises en cache seront des milliers, nous devons faire une classification des répertoires, sinon trouver et lire les fichiers cache deviendra un goulot d’étranglement d’efficacité, ce qui vide le CPU.
3 : Fichier de configuration
Nous devons configurer dans Web.config que le gestionnaire de cache soit un FileCacheProvider personnalisé, c’est-à-dire ajouter un nœud sous FileCacheProvider :- <caching>
- <outputCache defaultProvider="FileCache">
- <providers>
- <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
- </providers>
- </outputCache>
- </caching>
Code de copie
4 : Utilisation du cache
Nous supposons que l’utiliser sous le contrôle de MVC (si vous souhaitez l’utiliser dans une page ASP.NET, incluez < % dans le page@OutputCache VaryByParam="none » Duration="10 » %>), et vous pouvez voir qu’Index n’est pas mis en cache en sortie, tandis qu’Index2 est mis en cache pendant 10 secondes.
- 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 de copie 5 : Vérifie l’effet Le code ci-dessus, après avoir accédé à Index2, générera un fichier cache dans le dossier Cache, comme suit :
Évaluons maintenant la comparaison de performance entre le cache de sortie et le cache de sortie, en simulant 100 requêtes concurrentes de 100 utilisateurs comme suit :
|