Noi di Kinsta abbiamo una passione per la velocità: i nostri servizi di Hosting di Applicazioni, Hosting di Database e Hosting WordPress gestito vengono tutti eseguiti sulla rete Premium Tier e sulle macchine C2 più veloci della Google Cloud Platform. In più, ci affidiamo a Cloudflare per garantire velocità e sicurezza a decine di migliaia di clienti che vogliono distribuire i loro contenuti in tutto il mondo.

Per far sì che ciò accada, abbiamo imparato un paio di cose sull’uso di Cloudflare Workers e Workers KV per fornire regole di caching ottimizzate per contenuti statici e dinamici.

All’inizio del 2023, abbiamo raddoppiato la gestione della cache di Cloudflare, rendendo le cache più reattive alle modifiche di configurazione sul lato client e spostando il lavoro pesante di trasmissione degli aggiornamenti delle funzionalità dai nostri amministratori sul backend a Cloudflare Workers.

Il risultato principale è stato un aumento straordinario della percentuale di dati dei clienti salvati nella cache, con un incremento del 56,3% tra ottobre 2022 e marzo 2023.

Incremento della percentuale di successo degli hit di cache da ottobre 2022 a marzo 2023.
L’ottimizzazione attraverso Cloudflare Workers è diventata un punto di forza nel gennaio del 2023.

Cloudflare Workers e Workers KV ci permettono di personalizzare programmaticamente ogni richiesta e risposta con il minimo sforzo e una latenza inferiore. Non abbiamo più bisogno di distribuire le modifiche a centinaia di migliaia di container quando vogliamo implementare nuove funzionalità; possiamo replicare o implementare la funzionalità con Workers e distribuirla ovunque con pochi comandi e clic, risparmiando giorni di lavoro e manutenzione.

Routing delle richieste con Workers KV e Workers

Ogni dominio ospitato da Kinsta è una chiave e il suo valore contiene le impostazioni principali, come l’IP e la porta dell’origine, e un ID casuale unico. Con questi dati facilmente disponibili in Workers KV, possiamo usare Workers per analizzare, manipolare e fare il routing delle richieste al backend previsto. Usiamo anche Workers KV per memorizzare le opzioni di ottimizzazione dei clienti, come Polish, Image Resizing e Auto Minify.

Per fare il routing delle richieste verso IP e porte personalizzate, usiamo resolveOverride, una proprietà di Request specifica di Cloudflare. Ecco un esempio:

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

// Override the backend
cf.resolveOverride = customBackend;

Tuttavia, mentre Workers KV funzionava bene per fare il routing delle richieste, abbiamo presto notato risposte incoerenti nella nostra cache. A volte un cliente attivava Polish e, a causa della cache di un minuto di Workers KV, le nuove richieste arrivavano prima che Workers KV propagasse completamente la modifica, causando la memorizzazione nella cache di asset non ottimizzati.

Quando ciò accadeva, il cliente doveva cancellare di nuovo la cache manualmente. Non è lo scenario ideale. I clienti si sentivano frustrati e noi sprecavamo operazioni API e larghezza di banda GCP per svuotare continuamente la cache.

La chiave della cache è al centro di tutto

Dal momento che leggiamo sempre i dati Workers KV del dominio, ci siamo resi conto che potevamo fare il routing delle richieste e personalizzare la chiave della cache, aggiungendo elementi come l’ID del dominio e le caratteristiche che potevano influenzare l’asset, come Polish.

Oggi, la nostra chiave di cache è fortemente personalizzata per riflettere rapidamente ogni modifica apportata dal cliente al nostro pannello o all’API. Quando modifichiamo la chiave della cache usando i dati di Workers KV, nessuno deve più preoccuparsi di svuotare la cache. Non appena Workers KV propaga le modifiche, anche la chiave della cache cambia e noi richiediamo e mettiamo in cache una risorsa nuova.

Il modo più semplice per personalizzare la chiave della cache è aggiungere query params. Per esempio:

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

Naturalmente, è necessario verificare la presenza di parametri esistenti nell’URL per determinare quale connettore usare – ? o & – e assicurarsi di usare un identificatore univoco.

Poi, potete usare questa nuova chiave di cache per salvare la risposta con Cache API o Fetch o entrambi.

Cache di Workers KV

Le operazioni di Workers KV sono convenienti, ma i numeri possono accumularsi in fretta quando si attivano miliardi di operazioni di lettura al giorno.

Grazie alla personalizzazione della chiave di cache, abbiamo capito che potevamo mettere in cache i dati di Workers KV con Cache API, risparmiando sulle operazioni di lettura e possibilmente riducendo la latenza ed evitando molteplici richieste GET di Workers KV per visitatore. Poiché la risposta nella cache si basa ora sull’URL della richiesta combinato con i dati KV, non dobbiamo più preoccuparci di memorizzare nella cache i contenuti obsoleti.

Diagramma che mostra il flusso del processo quando si memorizzano nella cache i dati di Workers KV.
Il flusso del processo con la memorizzazione nella cache quando sono inclusi i dati di Workers KV.
Istogramma che mostra le risposte TTFB per vari scenari di caching.
Time to first byte medio in vari scenari di caching.

Tuttavia, a differenza di molte applicazioni, non possiamo mettere in cache Workers KV per periodi prolungati. I clienti di Kinsta provano continuamente nuove funzionalità, cambiano le impostazioni di Polish e Auto Minify, a volte escludono pagine o estensioni dalla cache, e vogliono vedere le loro modifiche in produzione il prima possibile.

È per questo che abbiamo deciso di mettere in microcache i dati di Workers KV, ovvero di memorizzare nella cache i contenuti dinamici o in costante cambiamento per un periodo di tempo molto breve, di solito inferiore ai 60 secondi.

È abbastanza semplice implementare la logica di caching del Workers KV.
Per esempio:

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;
};

(Opzionalmente, potete usare BetterKV di FlareUtils.)

In Kinsta abbiamo implementato un TTL di 30 secondi per la cache dei dati di Workers KV, riducendo le operazioni di lettura di circa l’80%.

Grafico che mostra la variazione delle operazioni di lettura nel tempo.
Diminuzione delle operazioni di lettura dopo l’implementazione di un TTL di 30 secondi per la cache dei dati di Workers KV.

Per saperne di più

Volete saperne di più su Workers e Workers KV? Date un’occhiata alla documentazione per sviluppatori di Workers KV di Cloudflare, oppure visitate la pagina web dedicata ai Workers KV di Cloudflare.

Questo articolo è stato pubblicato originariamente sul sito web di 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.