Na Kinsta, somos obcecados por velocidade: Nossos serviços de Hospedagem de Aplicativos, Hospedagem de Banco de Dados e Hospedagem Gerenciada de WordPress são executados na rede de nível premium e nas Máquinas C2 mais rápidas do Google Cloud Platform, e contamos com o Cloudflare para manter o ritmo para dezenas de milhares de clientes que desejam entregar seu conteúdo em todo o mundo com velocidade e segurança.

Ao fazer isso, aprendemos algumas coisas sobre o uso do Cloudflare Workers e do Workers KV para fornecer regras de cache otimizadas para conteúdo estático e dinâmico.

No início de 2023, dobramos o trabalho de controle de cache do Cloudflare, tornando os caches mais responsivos às alterações de configuração do lado do cliente e, ao mesmo tempo, transferindo o trabalho pesado por trás da transmissão de atualizações de recursos dos nossos administradores no backend para o Cloudflare Workers. Um resultado importante foi um aumento drástico na parcela de dados de clientes armazenados em cache com sucesso, aumentando 56,3% entre outubro de 2022 e março de 2023.

Data showing increase in percentage of successful cache hits over time.
A otimização por meio do Cloudflare Workers tornou-se um foco mais forte em janeiro de 2023.

O Cloudflare Workers e o Workers KV nos permitem personalizar programaticamente cada solicitação e resposta com o mínimo de esforço e menor latência. Não precisamos mais implantar alterações em centenas de milhares de contêineres quando queremos implementar novos recursos; podemos replicar ou implementar o recurso com o Workers e implantá-lo em todos os lugares com alguns comandos e cliques, poupando-nos dias de trabalho e manutenção.

Roteamento de solicitações com Workers KV e Workers

Cada domínio hospedado na Kinsta é uma chave, e seu valor contém pelo menos as configurações principais, como o IP e a porta da origem, e um ID aleatório exclusivo. Com esses dados facilmente disponíveis no Workers KV, podemos usar o Workers para analisar, manipular e encaminhar solicitações para o backend esperado. Também usamos o Workers KV para armazenar as opções de otimização do cliente, como Polish, Image Resizing e Auto Minify.

Para rotear solicitações para IPs e portas personalizados, usamos resolveOverride, uma propriedade Request específica do Cloudflare. Aqui está um exemplo:

// Assign KV values to variables
const { customBackend } = kvdata.kinstaConf;

// Override the backend
cf.resolveOverride = customBackend;

No entanto, embora o Workers KV funcionasse bem para rotear solicitações, logo notamos respostas inconsistentes em nosso cache. Às vezes, um cliente ativava o Polish e, devido ao cache de um minuto do Workers KV, novas solicitações chegavam antes que o Workers KV propagasse totalmente a alteração, fazendo com que colocássemos em cache ativos não otimizados. Quando isso acontecia, o cliente tinha que limpar o cache novamente de forma manual. Não era o cenário ideal. Os clientes ficavam frustrados e desperdiçávamos operações de API e largura de banda do GCP, limpando constantemente os caches.

A chave do cache é a chave

Como sempre lemos os dados do Workers KV do domínio, percebemos que poderíamos encaminhar solicitações e personalizar a chave do cache, acrescentando itens como o ID do domínio e recursos que poderiam afetar o ativo, como o Polish. Hoje, nossa chave de cache é altamente personalizada para refletir rapidamente cada alteração do cliente em nosso painel ou API. Ao modificar a chave do cache usando os dados do Workers KV, você não precisa mais se preocupar em limpar o cache. Assim que o Workers KV propaga as alterações, a chave do cache também é alterada, e nós solicitamos e armazenamos no cache em um novo ativo.

A maneira mais fácil de personalizar a chave do cache é anexar query params a ela. Por exemplo:

let cacheKey = `${request.url}?custom-cache-param-polish=lossy`

Obviamente, você precisa verificar se há parâmetros existentes na URL para determinar qual conector usar – ? ou & – e garantir que esteja usando um identificador exclusivo.

Em seguida, você pode usar essa nova chave de cache para salvar a resposta com a API de cache ou o Fetch, ou ambos.

Cache do Workers KV

As operações do Workers KV são acessíveis, mas os números podem se acumular quando você aciona bilhões de operações de leitura diariamente.

Graças à nossa personalização da chave de cache, percebemos que poderíamos armazenar em cache os dados do Workers KV com a API de cache, economizando em operações de leitura e possivelmente reduzindo a latência ao evitar várias solicitações GET do Workers KV por visitante. Como a resposta em cache agora se baseia na URL da solicitação combinado com os dados de KV, não precisamos mais nos preocupar com o armazenamento em cache de conteúdo obsoleto.

Chart showing process flow when caching Workers KV data.
O fluxo do processo com o armazenamento em cache dos dados do Workers KV inclui.
Chart showing TTFB responses for various caching scenarios.
Tempo médio para o primeiro byte em vários cenários de cache.

No entanto, ao contrário de muitos aplicativos, não podemos armazenar em cache o Workers KV por longos períodos. Os clientes da Kinsta estão constantemente experimentando novos recursos, alterando as configurações Polish e Auto Minify, às vezes excluindo páginas ou extensões do armazenamento em cache, e querem ver suas alterações em produção o mais rápido possível.

Foi então que decidimos colocar os dados do Workers KV em microcache – armazenando em cache conteúdo dinâmico ou constantemente alterado por um período muito curto, geralmente inferior a 60 segundos.

É muito simples implementar sua própria lógica de cache do Workers KV. Por exemplo:

const handleKVCache = async (event, myCustomDomain) => {
  // Try to get KV from cache first
  const cache = caches.default;
  let site_data = await cache.match( `https://${myCustomDomain}/some-string-ID-kv-data/` );

  // Valid KV cache match
  if (site_data && site_data.status === 200) {
    // ... modify your cached data if necessary, then return it
    return site_data;
  }

  // Invalid cache (expired, miss, etc), get data from KV namespace
  site_data = await KV_NAMESPACE.get(myCustomDomain.toLowerCase());
  
  // Cache valid KV responses with Cache API
  if (site_data) {
    let kvResponse = new Response(JSON.stringify(site_data), {status: 200});
    kvResponse.headers.set("Cache-Control", "public, s-maxage=30");
    event.waitUntil(cache.put(`https://${myCustomDomain}/some-string-ID-kv-data/`, kvResponse));
  }
  
  return site_data;
};

(Opcionalmente, você poderia usar o BetterKV do FlareUtils.)

Na Kinsta, implementamos um cache TTL de 30 segundos para os dados do Workers KV, reduzindo as operações de leitura em cerca de 80%.

Chart showing change in read operations over time.
Queda nas operações de leitura após a implementação de um TTL de 30 segundos para o cache de dados  do Workers KV.

Saiba mais

Você quer saber mais sobre o Workers e o Workers KV? Confira a documentação do desenvolvedor do Workers KV do Cloudflare ou comece visitando a página inicial dedicada ao Workers KV do Cloudflare.

Este artigo foi publicado originalmente no site do Cloudflare.

Paulo Paracatu

Paulo is a seasoned DevOps Engineer at Kinsta with a solid web hosting and optimization background. Equipped with Bash and JavaScript expertise, he uses Cloudflare Workers to continually improve user experiences in hosting.