Estratégias de Cache, Políticas, Cabeçalhos e Terminologias

Noções básicas de políticas de cache: terminologia, cabeçalhos HTTP e estratégias de cache

 

O armazenamento de conteúdo em cache é uma das formas mais eficazes de melhorar a experiência para os visitantes do seu site. O armazenamento em cache, ou armazenamento temporário de páginas e conteúdo, faz parte da estratégia de aceleração da navegação, usando protocolos HTTP ou HTTPS.

Neste artigo, discutiremos alguns dos conceitos básicos de armazenamento de conteúdo nas caches de navegadores e em proxies reversos (CDN). Vamos falar sobre as diferentes políticas de cache, os benefícios que o cache oferece, os efeitos colaterais que se deve ter em mente, e as diferentes estratégias para fornecer a melhor combinação entre desempenho e flexibilidade.

O que é cache?

Resumidamente, cache é o armazenamento de dados em uma memória de rápido acesso, visando acelerar a entrega de conteúdos que já foram solicitados anteriormente e armazenados nessa memória.

Por exemplo, uma página pode levar 3 segundos para ser gerada, contando o processamento do conteúdo, acesso ao banco de dados, etc. Mas se, após ser gerada pela primeira vez, armazenarmos essa página em um cache, as requisições futuras a esta página poderão ser entregue em milésimos de segundos. Isto aumentará muito o desempenho do seu site, reduzindo drasticamente a sobrecarga no seu servidor e melhorando a experiência do usuário.

Existem diferentes tipos de cache e cada um possui suas próprias características.

O cache de Web, ou web caching, é um tipo diferente de cache utilizado em CDNs e Navegadores, e é o foco deste artigo. O armazenamento em web cache é um recurso muito importante do protocolo HTTP/HTTPS, destinado a minimizar o tráfego de rede, ao mesmo tempo em que melhora a capacidade de resposta do sistema como um todo. Caches são encontrados em todos os níveis do percurso feito entre o conteúdo, no servidor, até o usuário, no navegador.

O web cache funciona armazenando, em um servidor intermediário ou em seu navegador, as respostas HTTP(S) para pedidos já efetuados, de acordo com determinadas regras. Futuras solicitações deste conteúdo poderão ser entregues a partir dos dados no cache mais próximo do usuário, em vez de reenviar o pedido de volta ao servidor original.

Benefícios:

O armazenamento em cache auxilia tanto os visitantes dos sites (consumidores de conteúdos), quanto os fornecedores de conteúdo. Alguns dos benefícios que o cache pode trazer são:

  • Redução dos custos de rede: o conteúdo pode ser armazenado em cache em vários pontos do caminho entre o usuário e a origem do conteúdo. Por exemplo: pode ser armazenado em uma CDN ou mesmo no próprio Navegador do usuário. Quando o conteúdo é armazenado próximo do usuário, os pedidos causarão menos atividade na rede e menos consumo de banda.
  • Melhor capacidade de resposta : o armazenamento em cache permite que o conteúdo seja recuperado mais rápido, pois a requisição não precisa ir até o servidor original e nem precisa ser recriado a partir do zero. Caches mantidos perto do usuário, como no cache do navegador, podem fazer essa recuperação instantaneamente.
  • Maior desempenho com o mesmo hardware : no servidor onde o conteúdo se originou, pode-se conseguir um grande aumento de desempenho, através de politicas de cache mais agressivas. Pode-se também aproveitar os servidores que estão ao longo do caminho para dividir a carga do sistema.
  • Disponibilidade de conteúdo durante interrupções de rede : usando as politicas de cache corretas, o armazenamento em cache pode ser usado para servir conteúdo para usuários mesmo se o seu servidor principal ficar fora do ar.

Terminologia:

Ao lidar com o armazenamento em cache, há alguns termos que provavelmente você encontrará e que talvez não sejam familiares. Alguns dos mais comuns estão abaixo:

  • Servidor de origem : o servidor de origem é o local onde está o conteúdo original. Se você atua como administrador de um servidor web, provavelmente esta é a máquina que você controla. Este servidor é responsável por servir qualquer conteúdo que não possa ser armazenado no cache, ou que tenha que, de tempos em tempos, ser atualizado.
  • Cache hit ratio (Taxa de acerto de cache) : a eficiência do sistema é medida conforme a taxa em que os dados são encontrados na cache. O Cache Hit Ratio é a relação entre o total de pedidos feitos à cache e o total destes pedidos que foram encontrados na cache. Uma alta taxa ‘hits’ (acertos) de cache significa que você está recuperando de forma rápida a maior parte do conteúdo desejado. Este é geralmente o resultado almejado pela a maioria dos administradores.
  • Freshness (Frescor): Freshness é um termo usado para descrever se um item dentro do cache ainda é considerado “fresco”, ou seja, apto para ser entregue ao usuário. O conteúdo em um cache só será usado para responder uma requisição se estiver dentro do tempo de ‘freshness’, ou período de validade, especificado pela política de cache. Caso contrário, ele será considerado obsoleto e será descartado. Um novo conteúdo será então requisitado ao servidor de origem.
  • Conteúdo obsoleto: um conteúdo é considerado obsoleto quando o tempo que ele está na cache é maior que o tempo definido como freshness. Conteúdo “expirado” é o mesmo que      “obsoleto”. Em geral, o conteúdo expirado não pode ser usado para responder às solicitações do cliente. O servidor de origem deve ser contactado para recuperar o novo conteúdo ou, pelo menos, confirmar que o conteúdo em cache ainda é atual.
  • Validação: os itens obsoletos no cache podem ser revalidados para atualizar seu tempo de expiração. A revalidação envolve uma verificação com o servidor de origem para ver se o conteúdo em cache ainda representa a versão mais recente do item, ou se precisa ser atualizado.
  • Invalidação: a invalidação é o processo de remoção de conteúdo do cache, antes mesmo que este extrapole a data de validade previamente especificada. Isso é necessário, por exemplo, se o item foi alterado no servidor de origem e existe uma cópia antiga no cache. Neste caso, a versão antiga que está no cache precisará ser invalidada.

Existem muitos outros termos sobre cache, mas os acima mencionados devem ajudar bastante por agora.

 

O que pode ficar em cache?

Alguns conteúdos são melhores para armazenamento em cache do que outros. Podemos citar, por exemplo:

  • Logotipos, fotos e imagens em geral
  • Imagens não rotativas (ícones de navegação, por exemplo)
  • Folhas de estilo (CSS)
  • Arquivos Javascript
  • Conteúdos disponíveis para download
  • Arquivos de mídia (fotos, vídeos, etc)

Estes conteúdos são conhecidos como conteúdos estáticos, pois tendem a mudar com muito pouca frequência. Com isso, eles podem ficar armazenados no cache por longos períodos de tempo.

Alguns itens que você precisa ter cuidado no armazenamento em cache são:

  • Páginas HTML
  • Imagens rotativas
  • JavaScript e CSS frequentemente modificados
  • Conteúdo solicitado com cookies de autenticação

Alguns itens que quase nunca devem ser armazenados em cache são:

  • Dados relacionados a operações sensíveis (informações bancárias, etc.)
  • Conteúdo que é específico de cada usuário e freqüentemente alterado

Além das regras gerais acima, é possível especificar políticas que permitem armazenar em cache, de forma adequada, diferentes tipos de conteúdo. Por exemplo, se os usuários autenticados veem a mesma versão do seu site, pode ser possível armazenar em cache essa visualização. Se os usuários autenticados tem uma visualização muito personalizada do site, você pode pedir para o navegador do usuário armazenar os dados no cache local, e estes dados não precisam ser armazenados em caches intermediárias.

 

Locais onde o conteúdo da Web fica em cache (ou “cacheado”)

O conteúdo de seu site pode ser armazenado em caches presentes em diferentes pontos do caminho de entrega dos dados:

  • Cache do navegador : os próprios navegadores da Web mantêm um pequeno cache. Normalmente, o navegador define uma política que determina os itens mais importantes para armazenar em cache. No entanto, através do cabeçalho HTTP(S), você pode também sugerir ao navegador os arquivos que ele deve armazenar no cache e por quanto tempo deve mantê-los.
  • Proxies de cache intermediário: qualquer servidor que fique entre o usuário e o seu servidor de origem pode armazenar alguns conteúdos em cache. Esses caches são normalmente mantidos por provedores ou outras empresas. Por exemplo, seu provedor de internet provavelmente possui um servidor de cache para dados do Netflix e Youtube.
  • Cache ou Proxy Reverso: em sua-infraestrutura você pode ter um servidor de cache para serviços back-end. Desta forma, o conteúdo pode ser servido a partir de um ponto mais próximo do cliente, ao invés de ter que acessar o servidor de origem a cada nova requisição. Uma CDN implementa este tipo de Cache ou Proxy Reverso.

Cada um desses locais pode armazenar itens no cache, de acordo com suas próprias políticas e as políticas de cache definidas na origem do conteúdo.

 

Caching Headers (Cabeçalhos de cache)

A própria entidade de cache (navegador, servidor, etc) pode decidir se deve ou não armazenar um conteúdo no sistema. No entanto, a maioria do comportamento de cache é determinada pela política de cache, que é definida pelo proprietário do conteúdo. Essas políticas são definidas principalmente através do uso de cabeçalhos HTTP específicos.

Através da evolução do protocolo HTTP, alguns cabeçalhos para cache foram surgindo, com diferentes níveis de sofisticação. Os descritos abaixo você necessariamente precisa conhecer:

  • Expires : O cabeçalho Expires é muito direto. Basicamente, ele define um tempo no futuro, quando o conteúdo irá expirar. Após a data definida em Expires, o conteúdo é considerado obsoleto e qualquer requisição precisará chegar até o servidor de origem.
  • Cache-Control : Esta é a substituição mais moderna do cabeçalho Expires . É bem suportado e implementa um mecanismo muito mais flexível. Em quase todos os casos é preferível utilizá-lo ao invés de Expires, mas não há problema utilizar os dois. Discutiremos as diferentes formas de configurar o Cache-Control um pouco mais tarde.
  • Etag : O cabeçalho Etag é usado para a validação do cache. O servidor de origem pode fornecer um Etag exclusivo para cada item, quando ele é inicialmente entregue. Quando o cache precisa validar o conteúdo de um item, ele pode enviar o Etag ao servidor, que dirá se aquele item ainda é válido ou se precisa ser atualizado (recebendo um o novo Etag). Pode também ser considera um tipo de fingerprint, ou impressão digital do arquivo.
  • Last-Modified : Este cabeçalho especifica a última vez que o item foi modificado. Isso pode ser usado como parte da estratégia de validação para garantir conteúdo atualizado.
  • Content-Length : Embora não envolvido especificamente no cache, o cabeçalho Content-Length é importante ao definir políticas de cache. Certos softwares se recusam a armazenar em cache o conteúdo se ele não conhece antecipadamente o tamanho, pois ele precisará reservar espaço de armazenamento.
  • Vary : um cache normalmente utiliza o endereço do ‘host’ (ou servidor) e o caminho do arquivo como identificador para armazenar um item na memória. O cabeçalho Vary pode ser usado para dizer ao cache que ele deve prestar atenção também a outros cabeçalhos adicionais, antes de decidir se um pedido é para um mesmo conteúdo. Isso é mais comumente utilizado em conjunto com cabeçalho Accept-Encoding, solicitando que o cache diferencie itens com conteúdo comprimido ou descompactado.

Um pouco mais sobre o Header Vary

O cabeçalho Vary fornece a capacidade de armazenar diferentes versões do mesmo conteúdo à custa de dividir as entradas no cache.

No caso de Accept-Encoding , a configuração do cabeçalho Vary permite uma distinção entre o conteúdo comprimido e não comprimido. Isso é necessário para atender corretamente os navegadores que não podem manipular o conteúdo compactado. Um ponto que mostra que Accept-Encoding é normalmente um bom candidato para Vary é o fato de que ele só tem dois ou três valores possíveis.

No entanto, à primeira vista uma outra boa ideia seria utilizar o Vary junto com o header User-Agent, como forma de diferenciar entre a versão de seu site para celulares e a versão convencional. No entanto, uma vez que os dados de User-Agent não são padronizados, você terá provavelmente muitas versões de um mesmo item no cache, deixando-o muito ineficiente. Portanto o cabeçalho Vary deve ser utilizado com moderação.

 

Como as flags de controle de cache impactam no desempenho

Anteriormente, mencionamos que o cabeçalho Cache-Control é usado para definir políticas de cache modernas. Uma série de instruções diferentes podem ser definidas usando este cabeçalho, com as instruções sendo separadas por vírgulas.

Algumas das opções de Cache-Control que você pode usar são:

  • no-cache : Esta instrução define que o conteúdo armazenado em cache deve ser re-validado em qualquer nova solicitação. Ou seja, esta flag marca o conteúdo como obsoleto imediatamente, mas permite que o cache use técnicas de revalidação para evitar baixar o item inteiro novamente.
  • no-store : esta instrução indica que o conteúdo não deve ser armazenado em cache de forma alguma. Isso é apropriado para, por exemplo, definir dados confidenciais.
  • public : marca o conteúdo como público, o que significa que ele pode ser armazenado em cache pelo navegador e em quaisquer outros caches intermediários. Nas solicitações que utilizam a autenticação HTTP, as respostas são marcadas como private por padrão. Este cabeçalho, public, server para substituir essa configuração.
  • private : marca o conteúdo como privado. O conteúdo privado pode ser armazenado pelo navegador do usuário, mas não deve ser armazenado em caches intermediárias. Isso geralmente é usado para dados que se referem a cada usuário.
  • max-age : Esta configuração define a “idade máxima” de um conteúdo, ou seja, o tempo máximo que ele pode ficar no cache sem ser revalidado com o servidor de origem. Em essência, isso substitui o cabeçalho Expires. Esta opção tem seu valor definido em segundos, com um tempo máximo de um ano (31536000 segundos).
  • s-maxage : Este cabeçalho é muito semelhante ao max-age, pois indica a quantidade de tempo que o conteúdo pode ser armazenado em cache. A diferença é que esta opção é aplicada apenas a caches intermediários e não ao navegador. Combinar isso com o cabeçalho “max-age” permite uma construção de políticas mais flexíveis de cache.
  • must-revalidate : Este header reforça que o tempo de expiração, indicado por max-ages-maxage ou por Expires, deve ser obedecido de forma estrita. O conteúdo obsoleto não pode ser entregue ao usuário sob nenhuma circunstância. Isso evita que o conteúdo em cache seja usado em caso de interrupções de rede, queda de servidores, ou cenários semelhantes.
  • proxy-revalidate : Isso funciona da mesma forma que a configuração acima (must-revalidate), mas se aplica apenas aos proxies, CDNs, ou servidores intermediários. Nesse caso, o navegador do usuário pode usar um conteúdo obsoleto se ocorrer uma falha na rede, mas serviços de caches intermediários devem, obrigatoriamente, revalidar o conteúdo se o mesmo ficar obsoleto.
  • no-transform : esta opção determina que o cache não tem permissão para modificar o conteúdo recebido, nem  por motivos de desempenho, nem  qualquer outra circunstância. Isso significa que, por exemplo, o cache não pode enviar versões compactadas do conteúdo se recebeu do servidor de origem uma versão não compactada.

Estas flags podem ser combinadas de diversas maneiras para configurar diferentes comportamentos de cache. Apenas algumas flags mutuamente exclusivos:

  • no-cache ou no-store são opostos ao comportamento padrão de uma cache
  • public e private são opostos entre si

A opção no-store substitui o no-cache se ambos estiverem presentes.

Para respostas a pedidos não autenticados, o cabeçalho public estará implícito e para respostas a pedidos autenticados, o cabeçalho private estará implícito. No entanto eles podem ser substituídos, incluindo a opção oposta no cabeçalho Cache-Control .

 

Desenvolvendo uma estratégia de cache

Em um mundo perfeito, tudo poderia ser armazenado em cache, de forma agressiva, e seus servidores só seriam acessados ocasionalmente para validar o conteúdo.  Isso geralmente não acontece na prática, então você precisa tentar definir algumas políticas de cache, visando o equilíbrio entre um cache de longo prazo e resposta às demandas de mudanças em um site.

Problemas comuns

Existem muitas situações em que o cache não pode ou não deve ser implementado devido à forma como o conteúdo é produzido (gerado dinamicamente para cada usuário ou a cada momento) ou a natureza do conteúdo (informações bancárias confidenciais, por exemplo).

Outro problema que muitos administradores podem enfrentear é a existência versões ainda válidas no cache, mesmo após novas versões das páginas terem sido publicadas.

Estes são problemas frequentemente encontrados e que podem ter sérios impactos no desempenho do cache ou na precisão do conteúdo que você está servindo. No entanto, podemos atenuar essas questões ao desenvolver políticas de cache antevendo tais problemas.

Recomendações gerais

Sua estratégia de cache será determinada pelas necessidades do seu site, no entanto, as recomendações a seguir podem ajudá-lo a tomar decisões razoáveis.

Existem alguns passos que você pode dar para aumentar a eficiência de seu cache, antes mesmo de se preocupar com detalhes ou cabeçalhos específicos. Algumas idéias são:

  • Estabeleça diretórios específicos para imagens, css e conteúdo compartilhado : Ao desenvolver seu site, coloque conteúdos em diretórios dedicados, que permitirá que você se refira facilmente a eles a partir de qualquer página em seu site. Isso aumenta a reusabilidade desses arquivos e a probabilidade de encontrá-los no cache.
  • Use o mesmo URL para se referir aos mesmos itens : como dissemos, o host e o caminho do arquivo são normalmente usados para identificar um conteúdo. Portanto, utilize sempre o mesmo URL para se referenciar a um mesmo conteúdo, evitando duplicar conteúdos idênticos no cache. A recomendação anterior torna isso significativamente mais fácil.
  • Use os sprites de imagem do CSS: os sprites de imagem CSS permitem colocar várias imagens e ícones em um único arquivo. Desta forma, você diminui o número de requisições ao seu servidor e aumenta a probabilidade de encontrar o arquivo com sprites no cache.
  • Armazene alguns Scripts e recursos externos localmente : se você utilizar scripts de javascript e outros recursos externos, considere hospedar esses recursos em seus próprios servidores caso os cabeçalhos não estejam sendo corretamente configurados no servidor externo. No entanto, note que você terá que sempre manter atualizada a cópia desse recurso externo em seu servidor.
  • Uso de fingerprint (impressão digital) : para conteúdo estático, como arquivos CSS e Javascript, pode ser interessante o uso do que chamamos de Impressão Digital, ou fingerprint. Isso significa adicionar um identificador exclusivo ao nome do arquivo para que, se o recurso for modificado, o novo recurso possa ser solicitado através do novo nome. Isso fará com que os novos pedidos ignorem a versão antiga do arquivo que poderá estar no cache. Há uma variedade de ferramentas que podem ajudar a criar impressões digitais e modificar, automaticamente, as referências a elas nos documentos HTML.

Sobre escolher adequadamente os cabeçalhos, para diferentes itens, pode-se utilizar as seguintes dicas:

  • Permitir que todos os caches armazenem itens genéricos : o conteúdo estático e o conteúdo que não é específico de um usuário podem, e devem, ser armazenados nos caches em todos os pontos da cadeia de entrega.
  • Permitir que os navegadores armazenem os recursos específicos do usuário : para o conteúdo referente a cada usuário, é geralmente aceitável e útil permitir o armazenamento no cache do navegador. Embora este conteúdo não seja apropriado para armazenar no cache de proxies intermediários, o cache no navegador permitirá uma recuperação instantânea nas próximas visitas destes usuários.
  • Faça exceções para conteúdos importantes e sensíveis ao tempo : se você tiver algum conteúdo que muda com o tempo, faça exceções às regras acima para que este conteúdo esteja sempre atualizado no cache. Por exemplo, se o seu site tiver um carrinho de compras, ele deve sempre refletir os itens no carrinho, imediatamente. Dependendo da natureza do conteúdo, as opções no-cache ou no-store podem ser definidas no cabeçalho Cache-Control para conseguir isso.
  • Forneça sempre validadores : os Validadores permitem que o conteúdo obsoleto seja atualizado sem precisar baixar o item inteiro novamente. Configurando os headers Etag e Last-Modified,permite-se que o cache valide se o conteúdo não foi modificado na origem, evitando baixá-lo novamente, reduzindo assim a carga na rede e aumentando a velocidade.
  • Defina longos tempos para a expiração do conteúdo de base : para otimizar o cache, os elementos que são solicitados como conteúdo de base para renderização do site, devem ter longos períodos de expiração. Isso geralmente é apropriado para itens como Imagens e arquivos CSS, que são usado para desenhar a página HTML solicitada pelo usuário. Definir tempos de expiração longos, combinados com impressões digitais, permitem que os caches armazenem esses recursos por longos períodos de tempo. Se os conteúdos mudarem, a nova impressão digital invalidará o item armazenado em cache e desencadeará o download do novo conteúdo.
  • Defina tempos curtos de expiração para o conteúdo original : para que o esquema acima funcione bem, conteúdos que dependem de cado usuário ou que mudam constantemente, devem ter tempo de expiração relativamente curto ou nem devem ser armazenados em cache. Normalmente são páginas dinâmicas, que geram um HTML que pode mudar conforme o momento, e que irão utilizar a ideia de impressões digitais (fingerprint) para carregar novos conteúdos estáticos caso seja necessário.

A ideia chave é encontrar um equilíbrio que favoreça um armazenamento em cache agressivo, ou seja, generalizado e por longo tempo, sempre que possível. Mas que preveja formas de invalidar alguns conteúdos no futuro, caso mudanças sejam feitas.

Seu site provavelmente terá uma combinação de:

  1. Itens agressivamente armazenados em cache
  2. Itens em cache com um curto período de expiração e a capacidade de revalidação
  3. Itens que não devem ser armazenados em cache

O objetivo é mover o conteúdo para as primeiras categorias quando possível, mantendo um nível aceitável de precisão.

 

Conclusão

Gastar um tempo para garantir que seu sistema tenha políticas de cache apropriadas terá um impacto significativo na velocidade do seu site. O armazenamento em cache permite que você reduza os custos com uso de banda. Seu servidor também poderá lidar com uma maior quantidade de tráfego com o mesmo hardware. E o mais importante, os clientes terão uma experiência mais rápida no seu site, o que pode levá-los a retornar com mais freqüência, aumentando as vendas de seu comércio eletrônico ou o numero de visitantes em seu blog.