Cloudflare Worker Cache用作快速KV存储的实现问题排查
Cloudflare Worker Cache 作为前置缓存层无法正常工作的问题排查与修复
我尝试将Cloudflare Worker Cache作为数据库的前置缓存层,但控制台持续触发“Failed to set cache value”错误,调用getCacheValue也无法返回内容。以下是我的实现代码:
const CACHE_URL_PREFIX = 'https://api.example.com/'; function getCache() { return caches.default; } function generateHash(str: string) { let hash = 0, i, chr; for (i = 0; i < str.length; i++) { chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } return hash.toString(36); } function toUniqueUrlPath(str: string) { let normalizedStr = str.trim(); normalizedStr = normalizedStr.toLowerCase(); normalizedStr = normalizedStr.replace(/[^a-z0-9 -]/g, '-'); normalizedStr = normalizedStr.replace(/\s+/g, '-'); const uniqueHash = generateHash(str); return `${normalizedStr}-${uniqueHash}`; } export function getCacheKey(key: string) { const normalizedKey = toUniqueUrlPath(key); const url = (CACHE_URL_PREFIX + normalizedKey) .replace(/\/+\/g, '/'); return new Request(url); } export async function getCacheValue<T>(key: string) { const cache = await getCache(); const cacheKey = getCacheKey(key); const cachedResponse = await cache.match(cacheKey); if (cachedResponse) { return await cachedResponse.json() as T; } return undefined; } export async function setCacheValue<T>(key: string, value: T, ttl: number) { const cache = await getCache(); const cacheKey = getCacheKey(key); const response = new Response(JSON.stringify(value), { headers: { 'Content-Type': 'application/json', 'Cache-Control': `public, max-age=${ttl}` } }); await cache.put(cacheKey, response); const valueFromCache = await getCacheValue<T>(key); if (!valueFromCache) { console.error('Failed to set cache value', { key, value, ttl, url: cacheKey.url, }); } }
问题分析与修复方案
1. 正则表达式语法错误
getCacheKey中的replace(/\/+\/g, '/')存在语法错误,正则表达式里的斜杠未正确转义,导致无法合并连续的URL斜杠。修正为:
const url = (CACHE_URL_PREFIX + normalizedKey).replace(/\/+/g, '/');
2. Cache 匹配规则不兼容
cache.match默认会严格匹配请求的方法、Headers等信息,而创建Request对象时隐式的默认值(比如Accept头)可能导致存入和查询的缓存键不匹配。需要在match时添加匹配选项,或统一Request的创建参数:
// 在getCacheValue中修改match调用 const cachedResponse = await cache.match(cacheKey, { ignoreMethod: true, ignoreVary: true }); // 或在getCacheKey中明确指定Request参数,确保一致性 return new Request(url, { method: 'GET', headers: new Headers({ 'Content-Type': 'application/json' }) });
3. Hash 生成逻辑冗余
toUniqueUrlPath中用原始字符串生成Hash,但前面已经做了归一化处理,改用归一化后的字符串生成Hash可以避免不必要的计算差异:
const uniqueHash = generateHash(normalizedStr);
修正后的完整代码
const CACHE_URL_PREFIX = 'https://api.example.com/'; function getCache() { return caches.default; } function generateHash(str: string) { let hash = 0, i, chr; for (i = 0; i < str.length; i++) { chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } return hash.toString(36); } function toUniqueUrlPath(str: string) { let normalizedStr = str.trim().toLowerCase(); normalizedStr = normalizedStr.replace(/[^a-z0-9 -]/g, '-'); normalizedStr = normalizedStr.replace(/\s+/g, '-'); const uniqueHash = generateHash(normalizedStr); return `${normalizedStr}-${uniqueHash}`; } export function getCacheKey(key: string) { const normalizedKey = toUniqueUrlPath(key); const url = (CACHE_URL_PREFIX + normalizedKey).replace(/\/+/g, '/'); return new Request(url, { method: 'GET', headers: new Headers({ 'Content-Type': 'application/json' }) }); } export async function getCacheValue<T>(key: string) { const cache = await getCache(); const cacheKey = getCacheKey(key); const cachedResponse = await cache.match(cacheKey, { ignoreMethod: true, ignoreVary: true }); if (cachedResponse) { return await cachedResponse.json() as T; } return undefined; } export async function setCacheValue<T>(key: string, value: T, ttl: number) { const cache = await getCache(); const cacheKey = getCacheKey(key); const response = new Response(JSON.stringify(value), { headers: { 'Content-Type': 'application/json', 'Cache-Control': `public, max-age=${ttl}` } }); await cache.put(cacheKey, response); const valueFromCache = await getCacheValue<T>(key); if (!valueFromCache) { console.error('Failed to set cache value', { key, value, ttl, url: cacheKey.url, }); } }
额外注意事项
- Cloudflare Worker Cache的键长度限制为2048字符,需确保生成的URL不超过该限制
- 可移除
setCacheValue中立即调用getCacheValue的校验逻辑,减少冗余缓存查询 - 若缓存内容频繁更新,需合理设置
max-age避免无效缓存
内容的提问来源于stack exchange,提问作者Marcus 123
相关产品推荐
相关产品推荐

