No artigo anterior, falei sobre o Application Caching, mecanismo capaz de armazenar objetos na memória do servidor para otimizar o acesso de novas requisições. Neste artigo irei abordar a segunda formar de caching disponibilizada pelo Asp.Net, o Page Output Caching.
Neste tipo de caching páginas ou seções dela são armazenadas na memória, com isso, novas solicitações não terão que realizar todo processamento para geração da página, o servidor simplesmente envia o HTML armazenado para o cliente que efetuou a requisição.
1. Passo a passo de uma requisição com Asp.Net
Para explicitar os benefícios do caching em páginas Asp.Net será mostrada as etapas de uma requisição web padrão, e compará-las com as etapas de uma requisição a uma página que já está em cache.
A imagem abaixo demonstra os eventos que ocorrem desde a solicitação do usuário no browser até a resposta do servidor, para uma página que não está em cache.
Figura 1: Passo a passo de uma requisição sem utilização do Output Caching.
O processo começa com a requisição do cliente. Ao chegar ao servidor, a página é encontrada e enviada ao Parse do Asp.Net, onde o código fonte será interpretado gerando instruções que serão enviadas para o compilador. Este é responsável por gerar o Assembly da página, que depois de criado é enviado para a memória do Runtime HTTP, onde as instruções serão executadas gerando a página solicitada. Quando uma segunda solicitação é realizada, as etapas de interpretação e compilação são puladas, pois o Assembly já está criado no servidor.
Agora imagine uma aplicação web com inúmeros clientes, cada cliente requisitando a mesma página que demanda um considerável processamento para sua criação, mas que não muda com tanta frequência. Para cada requisição todo o processamento visto anteriormente será necessário, se houverem 1000 requisições, 1000 vezes será executado, mesmo se o conteúdo não mudar.
A próxima imagem demonstra uma requisição a uma página que está no cache. Podemos notar a economia de recursos do servidor ao utilizar o Output Caching. Após a primeira requisição o conteúdo será armazenado em cache e todas as solicitações subsequentes receberão apenas o conteúdo HTML que já está armazenado, não sendo necessário o processamento da página.
Figura 2: Passo a passo de uma requisição com utilização do Output Caching.
2. Ativando o caching de página
Para ativar o mecanismo de caching em páginas .aspx é necessário informar no topo da página a diretiva @OutputCache da seguinte forma:
Listagem 1: Informando diretiva @OutputCache no Topo da Página
<%@ OutputCache ... %>
Essa diretiva possui vários parâmetros e de acordo com suas configurações vários resultados e comportamentos podem ser obtidos. As seções seguintes mostram como obter esses diferentes resultados.
2.1. Definindo o tempo de duração do caching
Para definir o tempo em que o cache de uma página é válido basta informar um valor inteiro para o parâmetro Duration, o valor informado irá corresponder ao tempo em segundos que a página estará em cache. Este é um parâmetro obrigatório, se não informado irá gerar uma exceção em runtime. O exemplo adiante ativa o caching da página por um tempo de trinta segundos.
Listagem 2: Definindo tempo de validade do caching
<%@ OutputCache Duration="30" VaryByParam="none"%>
2.2. Definindo a localização do caching
Outra configuração possível é informar onde o caching será armazenado. Configurando a propriedade Location é possível informar se o caching estará no cliente, no servidor ou em servidores proxy que participarem da solicitação. Os seguintes valores são possíveis:
- Any: O caching pode ser armazenado em qualquer mecanismo participante da requisição. Browser, servidores de proxy e o próprio servidor web;
- Client: Armazenado apenas no browser do cliente onde a solicitação foi originada;
- Downstream: Armazenado em qualquer dispositivo HTTP 1.1 que possui capacidade de cache e que participou da requisição, incluindo o cliente;
- Server: O caching estará armazenado apenas no servidor web que processou a requisição;
- None: Desabilita o caching;
- ServerAndClient: Armazena o caching apenas no servidor que processou a requisição e no cliente que a realizou, não permitindo o armazenamento em servidores proxy que por ventura tenham participado do processo.
O exemplo abaixo mostra como ativar o caching com duração de 10 segundos e armazená-lo apenas no servidor web.
Listagem 3: Ativando caching com duração de 10 segundos
<%@ OutputCache Duration="10" VaryByParam="none" Location="Server"%>
2.3. Parâmetro NoStore
A diretiva OutputCache possui ainda o parâmetro NoStore, que serve para informar aos browsers e servidores proxys, participantes da requisição, que não devem armazenar uma cópia permanente da página. É geralmente utilizado em páginas que possuem conteúdo sensível, como páginas de login. Configurado da seguinte maneira:
Listagem 4: Configurando OutputCache
<%OutputCache Duration="30" VaryByParam="none" NoStore=”true” %>
2.4. Armazenamento em cache de acordo com a QueryString
Existem cenários em que as páginas devem mudar seu conteúdo de acordo com parâmetros passados pela QueryString, mas apesar da mudança, o conteúdo específico de cada página/parâmetro não muda com frequência. Para esses cenários é possível utilizar o caching configurando o parâmetro VaryByParam, que consiste em uma lista de strings separadas por ponto-vírgula, indicando os parâmetros passados pela QueryString que devem ser considerados no cache. Observe o exemplo a seguir:
Listagem 5: Cache variável por parâmetro
<%@ OutputCache Duration="3600" VaryByParam="Id" %>
Neste exemplo acima, o caching foi ativado levando em consideração o parâmetro “Id”, passado via QueryString. Quando o servidor receber solicitações de uma página informando esse parâmetro, para cada valor passado será armazenada uma página no caching. Para cada uma das requisições abaixo o resultado da página irá ser armazenado no cache:
Listagem 6: Requisições para altrar o cache por parâmetro
PageOutputCaching/VaryByParam.aspx
PageOutputCaching/VaryByParam.aspx?Id=1
PageOutputCaching/VaryByParam.aspx?Id=2
O parâmetro VaryByParam é obrigatório, se não quiser utilizá-lo deve-se informar o valor “none”. Para informar que todos os parâmetros passados devem ser considerados no caching utiliza-se o valor “*”. Porém devemos evitá-lo, pois para cada combinação de valores enviados para os parâmetros, uma página será armazenada em cache, com isso o espaço em memória reservado poderá rapidamente ficar escasso e outras informações mais importantes serem removidas.
2.5. Armazenamento em cache de acordo com controles da página
Assim como ocorre com a variação pela QueryString, é possível armazenar páginas em cache de acordo com os valores dos controles utilizados no Asp.Net. Para fazer isto basta configurar o parâmetro VaryByControl informando uma lista de ID’s dos controles que devem ser considerados no caching. Quando se utiliza o VaryByControl não é necessário informar o VaryByParam. O exemplo abaixo mostra como configurar o caching para que para cada valor selecionado e submetido do DropDowList “ddlTema” seja armazenada uma versão da página em cache.
Listagem 7: Cache variável por controle
<%--Configuração--%>
<%@ OutputCache Duration="1000000" VaryByControl="ddlTema" %>
2.6. Armazenamento em cache de acordo com parâmetro customizado
Também é possível, através de um valor customizado, definir como será o armazenamento em cache. Deve-se configurar o parâmetro VaryByCustom na página com um identificador, e no arquivo Global.asax sobrescrever o método GetVaryByCustomString, informando como deve ser realizado o processo. Abaixo um exemplo de como criar um caching da página de acordo com o método de requisição (Get ou Post).
Na página:
Listagem 8: Configurando a página para cache customizado
<%@ OutputCache Duration="1000000" VaryByParam="none" VaryByCustom="metodo"%>
Global.asx:
Listagem 9: Configurando o Global.asax para cache customizado
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom == "metodo")
return context.Request.RequestType;
else
return base.GetVaryByCustomString(context, custom);
}
2.7. Armazenamento em cache de acordo com cabeçalhos HTTP
Outra forma de mudar o comportamento do caching é configurando o parâmetro VaryByHeader, que recebe uma lista de propriedades enviadas com os cabeçalhos HTTP. Configurando esse parâmetro, par
...