合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
# 使用缓存 工作者提供了一种使用Cloudflare的经典CDN以及私有缓存空间来自定义缓存行为的方法。要了解缓存的好处,请参阅我们的学习中心关于“[什么是缓存?”](https://www.cloudflare.com/learning/cdn/what-is-caching/)的文章[。](https://www.cloudflare.com/learning/cdn/what-is-caching/) ## 与Cloudflare缓存交互 从概念上讲,有两种使用工作器与Cloudflare的Cache进行交互的方式: * 将响应存储在Cloudflare的经典CDN上,可以通过调用`fetch()`Workers脚本来完成。通过Worker进行的自定义缓存行为包括: * 设置Cloudflare缓存规则(即对cf对象进行操作) * 设置自定义缓存头(即缓存控件)。这可能会影响浏览器以及Cloudflare缓存行为。 * 使用来自Workers脚本的Cache API,将响应存储在与Cloudflare的传统缓存分开的区域范围的命名空间中。甚至可以控制没有代理到Cloudflare的资产的缓存行为。 我们将不在本文中讨论,但其他控制Cloudflare缓存的方法包括:页面规则和Cloudflare缓存设置。如果您希望避免编写一些具有一定控制粒度的Javascript,我强烈建议您阅读“[如何控制Cloudflare的缓存”一文](https://support.cloudflare.com/hc/en-us/articles/202775670)。 ### [缓存API](https://developers.cloudflare.com/workers/reference/apis/cache) 缓存API使用Cloudflare的全球网络为每个区域创建一个专用的缓存密钥名称空间。缓存对象存储在处理请求的本地数据中心中,不会复制到其他数据中心。 **缓存API与`fetch()`有何不同?**`fetch()`请求一个URL并根据您的Cloudflare设置自动应用缓存规则。它不允许您在对象到达缓存之前对其进行修改,或者在发出请求之前检查对象是否在缓存中。 缓存API的`caches.default`缓存对象使您可以: * 当(且仅)使用缓存URL时,获取URL的响应`caches.default.match(..)`。 * 使用`caches.default.put(..)`和显式删除将响应明确存储在缓存中`caches.default.delete(..)`。 **缓存API的使用限制是什么?** * 每个请求共50个`put()`,`match()`或`delete()`呼叫,使用与相同的配额`fetch()` * `put()`每个请求总共5 GB * 免费,专业版,商务版: * 每个`put()`具有有效`Content-Length`标头的最大512MB * 高达512MB的`put()`使用`Transfer-Encoding: chunked`。请注意,这会阻止后续`put()`的,直到传输完成。 * 对于企业: * 每个`put()`带有有效`Content-Length`标头的最大5GB * 高达5GBs了`put()`与`Transfer-Encoding: chunked`。请注意,这会阻止后续`put()`的,直到传输完成。 使用缓存API*不会*设置`Cf-Cache-Status`标头。 ### Cloudflare的CDN 默认情况下,Cloudflare的传统CDN即使没有使用Worker也可以在静态资产上运行。尽管两者都存在于Cloudflare的全球网络中,但Cache API使用的命名空间与Cloudflare的CDN分开存储。 在Workers的上下文中[`fetch`](https://developers.cloudflare.com/workers/reference/apis/fetch),运行时提供的与传统Cloudflare缓存进行通信。首先,`fetch`检查URL是否与其他区域匹配。如果是这样,它将读取该区域的缓存。否则,即使URL是针对非Cloudflare站点的,它也会读取其自身区域的缓存。缓存设置`fetch`基于您的Cloudflare设置自动应用缓存规则。`fetch`不允许您在*对象*到达缓存之前对其进行*修改或检查*,但是允许您修改对象的*缓存方式*。 当响应填充高速缓存时,响应标头包含`CF-Cache-Status: HIT`。您可以告诉一个对象是否正在尝试缓存(如果有人看到)`CF-Cache-Status`。 Phew ..听起来很多,但是一些示例应该会很有道理。以下是根据给定请求自定义Cloudflare CDN的缓存行为的方法: #### 缓存HTML(或其他未列入白名单的文件扩展名): ~~~javascript // Force Cloudflare to cache an asset fetch(event.request, { cf: { cacheEverything: true } }) ~~~ 将缓存级别设置为“缓存一切”将覆盖资产的默认“可缓存性”。对于TTL,Cloudflare仍将依赖由原点设置的标头。 #### 覆盖TTL: ~~~javascript // Force response to be cached for 300 seconds. fetch(event.request, { cf: { cacheTtl: 300 } }) ~~~ 此选项强制Cloudflare缓存此请求的响应,而不管响应上看到什么标头。这等效于设置两个页面规则:[“边缘缓存TTL”](https://support.cloudflare.com/hc/en-us/articles/200168376-What-does-edge-cache-expire-TTL-mean-)和[“缓存级别”(以“缓存所有内容”)](https://support.cloudflare.com/hc/en-us/articles/200172266-What-do-the-custom-caching-options-mean-in-Page-Rules-)。 #### 根据起点响应代码进行覆盖: *此功能仅适用于企业用户。* ~~~javascript // Force response to be cached for 86400 seconds for 200 status codes, 1 second for 404, // and do not cache 500 errors fetch(request, { cf: { cacheTtlByStatus: { '200-299': 86400, 404: 1, '500-599': 0 } } }) ~~~ 此选项是功能的一个版本,该`cacheTtl`功能根据响应的状态码选择TTL。如果对此请求的响应具有匹配的状态代码,则Cloudflare将在指令时间内进行缓存,并覆盖原始服务器发送的缓存指令。 TTL值: * TTL正值表示以秒为单位的Cloudflare应该为之缓存资产多长时间 * `0`TTL将导致资产被缓存,但会立即过期(每次都从原始位置重新验证) * `-1`,否则任何负值将指示Cloudflare根本不缓存 #### 自定义缓存键 *此功能仅适用于企业用户。* 一个请求的缓存键决定了两个请求是否“相同”以进行缓存。如果一个请求与先前的某个请求具有相同的缓存键,那么我们可以为两个请求提供相同的缓存响应。有关缓存键的更多信息,请参见[使用自定义缓存键](https://support.cloudflare.com/hc/en-us/articles/115004290387)支持文章。 ~~~javascript // Set cache key for this request to "some-string". fetch(event.request, { cf: { cacheKey: 'some-string' } }) ~~~ 通常,Cloudflare根据请求的URL计算请求的缓存密钥。但是有时候,出于缓存目的,您希望将不同的URL视为相同。例如,假设您的网站内容同时由Amazon S3和Google Cloud Storage托管-您在两个地方都拥有相同的内容,并且使用Worker来在两者之间随机平衡。但是,您不想最终缓存内容的两个副本。您可以利用自定义缓存键基于原始请求URL而不是子请求URL进行缓存: ~~~javascript addEventListener('fetch', event => { let url = new URL(event.request.url) if (Math.random() < 0.5) { url.hostname = 'example.s3.amazonaws.com' } else { url.hostname = 'example.storage.googleapis.com' } let request = new Request(url, event.request) event.respondWith( fetch(request, { cf: { cacheKey: event.request.url }, }), ) }) ~~~ 请记住,代表不同区域进行操作的Worker不能影响彼此的缓存。仅在您自己的区域内发出请求时(在上面的示例中`event.request.url`是存储的键),或对不在Cloudflare上的主机的请求时,您才能覆盖缓存键。向另一个Cloudflare区域(例如,属于另一个Cloudflare客户)发出请求时,该区域将完全控制如何在Cloudflare中缓存其自身的内容;您无法覆盖它。 ### 覆盖浏览器缓存(缓存控制标头) 浏览器通过Cloudflare发送的响应标头确定要缓存的内容。 ~~~javascript async function fetchAndApply(request) { let response = await fetch(request) // Make response headers mutable response = new Response(response.body, response) response.headers.set('Cache-Control', 'max-age=1500') return response } ~~~