in ASP.NET

.NET Core e Cache: Memory Cache

Um dos fatores de sucesso de uma aplicação em termos de performance e de escalabilidade é a maneira de como foi desenvolvida uma estratégia para poder economizar/poupar algumas atividades como acesso a disco, banco de dados e operações que consumam muito CPU.

O Cache é um recurso muito importante para estes fins, com ele evitamos que certas partes de código sejam executadas várias vezes de maneira desnecessária. Por exemplo: não se faz necessário para cada usuário do seu site que você consulte o banco de dados ou um xml para montar a estrutura do menu, para este fim você pode definir um tempo de atualização e guardar a informação do menu  em um cache (em memória por exemplo) evitando assim IOs desnecessários.

Com a nova versão do ASP.NET Core a maneira de utilizar cada tipo de recurso mudou, ele é um framework muito mais modularizado e performático, onde nós desenvolvedores precisamos escolher conscientemente cada recurso que vamos utilizar.

Pensando nestas mudanças decidi escrever uma série com 4 posts abordando as diversas camadas e técnicas para utilizar Cache com .NET Core, vou abordar temas como: Cache de Objetos, OutputCache, Sistemas de Cache Distribuídos e Cache Http.

Neste post vou abordar o Cache de Objetos, que no caso do .NET Core consiste em manter objetos na memória do servidor, com um sistema de controle de validade, inserção, atualização, remoção e retorno dos objetos.

Começando

Para começar vou criar um projeto com ASP.NET Core (estou utilizando o Visual Studio 2015 com SP3 e o Tooling Preview2 para .NET Core https://www.microsoft.com/net/core#windows)

Com o projeto criado, eu vou adicionar dois pacotes no meu project.json

image

Vou utilizar o Microsoft.Extensions.Caching.Abstractions e o Microsoft.Extensions.Caching.Memory, lembrando que precisei colocar eles dentro do nó chamado “dependencies”, após salvar o arquivo .json o Visual Studio irá restaurar os pacotes (caso não esteja utilizando o VS pode ser feito manualmente).

image

"Microsoft.Extensions.Caching.Abstractions": "1.0.0",
"Microsoft.Extensions.Caching.Memory": "1.0.0"

O próximo passo será adicionar o MemoryCache na configuração da minha aplicação com o método ConfigureServices do Startup.cs.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddMvc();
    }
    //...//
}

Feito isto, já temos o injetor de dependência configurado e podemos utilizar o MemoryCache, para este exemplo vou utilizar no HomeController, lembrando que o ideal é separar o uso do cache em outras classes e organizar o projeto.

No construtor do HomeController vou dizer que ele recebe uma instância de IMemoryCache:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

namespace DemoMemoryCache.Controllers
{
    public class HomeController : Controller
    {
        private IMemoryCache _memoryCache;
        public HomeController(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }
    }
}

Com isto podemos utilizar o objeto _memoryCache em nossas Actions por exemplo:

public IActionResult Index()
{
    var chaveDoCache = "chave_do_cache";
    string dataAtual;

    if (!_memoryCache.TryGetValue(chaveDoCache, out dataAtual))
    {
        var opcoesDoCache = new MemoryCacheEntryOptions()
        {
            AbsoluteExpiration = DateTime.Now.AddSeconds(30)
        };

        dataAtual = DateTime.Now.ToString();

        _memoryCache.Set(chaveDoCache, dataAtual, opcoesDoCache);
    }

    ViewBag.Data = dataAtual;

    return View();
}

Note que no código acima que uma das primeiras coisas a se fazer é definir a chave que será utilizada para acessar o valor do objeto que será posto no cache, feito isto podemos utilizar o TryGetValue para entender se o objeto que queremos buscar já está no cache, caso ele esteja, não executaremos o código que processa o valor e salva no cache (parte interna do if).

Temos algumas configurações em um objeto chamado opcoesDoCache, é nele que definimos quando tempo aquele cache é valido e quais as configurações vamos utilizar, feito isto tempos uma parte que significa “processar” o valor (que no exemplo é um DateTime.Now.ToString()), com o valor processado, vamos salvar ele no cache utilizando o método Set do _memoryCache.

Antes de retornar a View, vamos atribuir o valor (vindo do cache ou não) para uma ViewBag chamada Data que vamos chamar na view Index.cshtml

image

Executando

Ao executar podemos notar que o “processamento” do DateTime.Now.ToString() só acontece a cada 30 segundos Alegre

image

Mesmo a página sendo requisitada várias vezes, o valor continua sendo obtido do cache por 30 segundos:

image

Este é um exemplo de como utilizar e configurar o MemoryCache em nossas aplicações, na prática economizar uma ou duas consultas a um banco de dados(por exemplo) pode significar uma melhoria grande no tempo de resposta e na escalabilidade de nossas aplicações.

Em breve publicarei outros posts abordando os outros assuntos sobre Cache e .NET Core

abs

Rodolfo