如何利用Cloudflare Workers将缓存命中率提高56%

如何利用Cloudflare Workers将缓存命中率提高56%

在实现依靠Cloudflare提供高速、安全的内容分发服务的过程中,我们学会了如何使用 Cloudflare Workers 和 Workers KV 为静态和动态内容提供优化的缓存规则。

2023 年初,我们在 Cloudflare 缓存管理方面加倍努力,使缓存对客户端配置更改的响应速度更快,同时将广播功能更新的重任从后台管理员手中转移到 Cloudflare Workers。一个重要成果是成功缓存的客户数据份额大幅增加,在 2022 年 10 月至 2023 年 3 月期间增加了 56.3%。

通过 Cloudflare Workers 进行的优化成效

通过 Cloudflare Workers 进行的优化成效

Cloudflare Workers 和 Workers KV 允许我们以最小的工作量和更低的延迟对每个请求和响应进行编程定制。当我们要实施新功能时,不再需要将更改部署到成百上千的容器中;我们可以使用 Workers 复制或实施该功能,只需几个命令和点击即可将其部署到各个地方,从而节省了数天的工作和维护时间。

使用Workers KV和Workers请求路由

每个域都是一个键,其值至少包含核心设置(如源 IP 和端口)和一个唯一的随机 ID。有了 Workers KV 中的这些数据,我们就可以使用 Workers 来分析、处理请求,并将请求路由到预期的后端。我们还使用 Workers KV 来存储客户优化选项,如抛光、图像大小调整和自动最小化。

要将请求路由到自定义 IP 和端口,我们使用特定于 Cloudflare 的请求属性 resolveOverride。下面是一个示例:

// Assign KV values to variables
const { customBackend } = kvdata.kinstaConf;
// Override the backend
cf.resolveOverride = customBackend;

然而,虽然 Workers KV 可以很好地路由请求,但我们很快就发现缓存中的响应不一致。有时,客户激活了波兰语,由于 Workers KV 的一分钟缓存,新请求在 Workers KV 完全传播更改之前就已到达,导致我们缓存了未优化的资产。发生这种情况时,客户不得不再次手动清除缓存。这种情况并不理想。客户感到沮丧,而我们则浪费了 API 操作和 GCP 带宽,不断清除缓存。

缓存键是关键

由于我们总是读取域的 Workers KV 数据,我们意识到我们可以路由请求并自定义缓存密钥,添加域的 ID 和可能影响资产的功能(如波兰语)。如今,我们的缓存密钥经过了大量定制,可以快速反映面板或 API 中的每一个客户变化。通过使用 Workers KV 的数据修改缓存密钥,再也不用担心清除缓存的问题了。一旦 Workers KV 传播了更改,缓存密钥也会随之更改,我们就会请求并缓存新的资产。

自定义缓存密钥的最简单方法是向其添加 query params 。例如:

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

当然,您需要检查 URL 中的现有参数,以确定使用哪个连接器( ?& ),并确保您使用的是唯一标识符。

然后,您就可以使用这个新的缓存密钥,通过缓存 API 或 Fetch(或两者)保存响应。

Workers KV缓存

Workers KV 操作费用低廉,但如果每天触发数十亿次读取操作,数字就会堆积如山。

由于我们对缓存密钥进行了定制,我们意识到可以通过缓存 API 来缓存 Workers KV 数据,从而节省读取操作,并可能通过避免每个访问者多次 Workers KV GET 请求来降低延迟。由于缓存响应现在是基于请求的 URL 和 KV 数据,我们不再需要担心缓存过期内容。

包括缓存 Workers KV 数据的流程

包括缓存 Workers KV 数据的流程。

在各种缓存情况下,到第一个字节的平均时间

在各种缓存情况下,到第一个字节的平均时间。

然而,与许多应用程序不同,我们无法长时间缓存 Workers KV。Kinsta 的客户不断尝试新功能,更改波兰语和自动最小化设置,有时会将页面或扩展排除在缓存之外,他们希望尽快在生产中看到自己的更改。

因此,我们决定对我们的 Workers KV 数据进行微缓存–在很短的时间内(通常少于 60 秒)缓存动态或不断变化的内容。

实现自己的 Workers KV 缓存逻辑非常简单。例如:

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

(也可以使用 FlareUtils 的 BetterKV)。

下图为 Workers KV 数据实施了 30 秒的缓存 TTL,将读取操作减少了约 80%。

为 Workers KV 数据缓存设置 30 秒 TTL 后,读取操作量减少。

为 Workers KV 数据缓存设置 30 秒 TTL 后,读取操作量减少。

学习更多

想了解有关 Workers 和 Workers KV 的更多信息?请查看 Cloudflare Workers KV 开发文档,或访问 Cloudflare 专门的 Workers KV 主页

评论留言