Este artigo é um artigo espelhado de tradução automática, por favor clique aqui para ir para o artigo original.

Vista: 16824|Resposta: 0

[ASP.NET] Construa um cache de arquivos personalizado ASP.NET otimização de desempenho

[Copiar link]
Publicado em 19/04/2015 22:06:12 | | | |
ASP.NET cache de saída (ou seja, HTML estático) era baseado em memória até o .NET 4.0. Isso significa que, se nosso site contiver muito cache, é fácil consumir memória local. Agora, com a ajuda de . Em OutputCacheProvider no .NET 4.0, temos várias opções para criar nosso próprio cache. Por exemplo, podemos armazenar o cache de saída HTML em um servidor de cluster distribuído com memcache ou em MongoDB (um banco de dados orientado a documentos comumente usado, leia http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx). Claro, também podemos armazenar o cache como um arquivo no disco rígido, que é a forma mais barata de fazer isso considerando a escalabilidade, e este artigo é sobre como construir um cache de arquivos personalizado.
1:FornecedorCacheSaída
OutputCacheProvider é uma classe base abstrata que precisamos sobrescrever quatro de seus métodos, que são:
Método Add para inserir o item especificado no cache de saída.
Get, que retorna uma referência ao item especificado no cache de saída.
Método Remove para remover o item especificado do cache de saída.
set, insere o item especificado no cache de saída e sobrescreve o item se ele estiver em cache.
2: Crie sua própria classe de tratamento de cache de arquivos
O tipo é FileCacheProvider, e o código é o seguinte:

  1. public class FileCacheProvider : OutputCacheProvider
  2. {
  3.     private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  4.     public override void Initialize(string name, NameValueCollection attributes)
  5.     {
  6.         base.Initialize(name, attributes);
  7.         CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]);
  8.     }

  9.     public override object Add(string key, object entry, DateTime utcExpiry)
  10.     {
  11.         Object obj = Get(key);
  12.         if (obj != null)    //这一步很重要
  13.         {
  14.             return obj;
  15.         }
  16.         Set(key,entry,utcExpiry);
  17.         return entry;
  18.     }

  19.     public override object Get(string key)
  20.     {
  21.         string path = ConvertKeyToPath(key);
  22.         if (!File.Exists(path))
  23.         {
  24.             return null;
  25.         }
  26.         CacheItem item = null;
  27.         using (FileStream file = File.OpenRead(path))
  28.         {
  29.             var formatter = new BinaryFormatter();
  30.             item = (CacheItem)formatter.Deserialize(file);
  31.         }

  32.         if (item.ExpiryDate <= DateTime.Now.ToUniversalTime())
  33.         {
  34.             log.Info(item.ExpiryDate + "*" + key);
  35.             Remove(key);
  36.             return null;
  37.         }
  38.         return item.Item;
  39.     }


  40.     public override void Set(string key, object entry, DateTime utcExpiry)
  41.     {
  42.         CacheItem item = new CacheItem(entry, utcExpiry);
  43.         string path = ConvertKeyToPath(key);
  44.         using (FileStream file = File.OpenWrite(path))
  45.         {
  46.             BinaryFormatter formatter = new BinaryFormatter();
  47.             formatter.Serialize(file, item);
  48.         }
  49.     }
  50.       
  51.     public override void Remove(string key)
  52.     {
  53.         string path = ConvertKeyToPath(key);
  54.         if (File.Exists(path))
  55.             File.Delete(path);
  56.     }

  57.     public string CachePath
  58.     {
  59.         get;
  60.         set;
  61.     }

  62.     private string ConvertKeyToPath(string key)
  63.     {
  64.         string file = key.Replace('/', '-');
  65.         file += ".txt";
  66.         return Path.Combine(CachePath, file);
  67.     }
  68. }

  69. [Serializable]
  70. public class CacheItem
  71. {
  72.     public DateTime ExpiryDate;
  73.     public object Item;

  74.     public CacheItem(object entry, DateTime utcExpiry)
  75.     {
  76.         Item = entry;
  77.         ExpiryDate = utcExpiry;
  78.     }
  79. }
Copiar código
Existem dois lugares que precisam de atenção especial:
No método Add, há um julgamento condicional que deve ser tratado dessa forma, caso contrário o mecanismo de cache irá armazenar o primeiro resultado em cache, e o cache expirará após a data de expiração e não será reconstruído.
No programa de exemplo, simplesmente colocamos o cache no diretório cache, e na prática prática do projeto, considerando que as páginas em cache serão milhares, devemos fazer a classificação de diretórios, caso contrário encontrar e ler arquivos de cache se tornará um gargalo de eficiência, o que drenará a CPU.
3: Arquivo de configuração

Precisamos configurar no Web.config para que o handler de cache seja um FileCacheProvider personalizado, ou seja, adicionar um nó em FileCacheProvider:
  1. <caching>
  2.   <outputCache defaultProvider="FileCache">
  3.     <providers>
  4.       <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
  5.     </providers>
  6.   </outputCache>
  7. </caching>
Copiar código

4: Uso do cache

Assumimos que usar isso sob controle do MVC (se quiser usá-lo em uma página de ASP.NET, inclua <% no page@OutputCache VaryByParam="none" Duration="10" %>), e você pode ver que o Index não está em cache de saída, enquanto o Index2 fica em cache por 10 segundos.
  1. public class HomeController : Controller
  2. {
  3.     private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  4.     static string s_conn = "Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;";
  5.     public ActionResult Index()
  6.     {
  7.         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()"))
  8.         {
  9.             ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
  10.         }
  11.         return View();
  12.     }

  13.     [OutputCache(Duration = 10, VaryByParam = "none")]
  14.     public ActionResult Index2()
  15.     {
  16.         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()"))
  17.         {
  18.             ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
  19.         }
  20.         return View();
  21.     }
  22. }
Copiar código
5: Verifique o efeito
O código acima, após acessar o Index2, gerará um arquivo de cache na pasta Cache, da seguinte forma:

Agora, vamos avaliar a comparação de desempenho entre o cache de saída e o cache de saída, simulando 100 solicitações simultâneas de 100 usuários da seguinte forma:








Anterior:Ciclo de vida da Session
Próximo:C#. .NET para prevenir ataques de injeção SQL
Disclaimer:
Todo software, material de programação ou artigos publicados pela Code Farmer Network são apenas para fins de aprendizado e pesquisa; O conteúdo acima não deve ser usado para fins comerciais ou ilegais, caso contrário, os usuários terão todas as consequências. As informações deste site vêm da Internet, e disputas de direitos autorais não têm nada a ver com este site. Você deve deletar completamente o conteúdo acima do seu computador em até 24 horas após o download. Se você gosta do programa, por favor, apoie um software genuíno, compre o registro e obtenha serviços genuínos melhores. Se houver qualquer infração, por favor, entre em contato conosco por e-mail.

Mail To:help@itsvse.com