banner
innei

innei

写代码是因为爱,写到世界充满爱!
github
telegram
twitter

緩存標頭和利用邊緣網絡加速訪問

本文以 Cloudflare + Vercel 為例。

了解快取標頭#

在生產中,我們通常會利用 Redis 去快取介面數據。對於前端應用來說,我們一般會利用內容分發網路(CDN)去快取頁面和其他靜態資源。

我們知道 HTTP 標頭 cache-control 可以用來強快取資源。

例如,cache-control: max-age=60 表示資源在 60 秒內不會過期,瀏覽器如果不使用強制刷新的話(例如請求標頭含有cache-control: max-age=0)可以直接使用本地快取。

在邊緣網路或是內容分發網路中,一般都能相關的標頭進行快取。

比如:s-maxage 的值。

Note

s-maxage

s-maxage 回應指令表示回應在共享快取中保持新鮮的時間。s-maxage 指令會被私有快取忽略,並且會覆蓋共享快取中 max-age 指令或 Expires 標頭指定的值(如果存在)。

Cache-Control: s-maxage=604800

參考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage

而這個值,一般都被 CDN 或者邊緣網路用來控制快取時間。

在 Vercel 中。Cache 章節中,告訴我們可以使用這個值去控制一個 API 回應的快取時間。另外也提供了 Vercel 私有的 HTTP 標頭,例如 Vercel-CDN-Cache-Control

在 Cloudflare 中,When to use CDN-Cache-Control 中的例子可以更好的幫助理解資源在各端的快取控制。

Headers:

Cache-Control: max-age=14400, s-maxage=84000
Cloudflare-CDN-Cache-Control: max-age=24400
CDN-Cache-Control: max-age=18000

快取行為:

快取快取 TTL (秒)
原始伺服器快取14400
網路共享快取84000
Cloudflare 邊緣24400
其他 CDN18000
瀏覽器快取14400

上表中,Cloudflare 可以消耗回應頭中的 cache-control: s-maxageCloudflare-CDN-Cache-Control 控制資源在 Cloudflare 分發網和邊緣網路的快取。

透過快取標頭,可以更快的讓用戶訪問到資源,減少伺服器的負載。

以 Vercel 部署的 Next.js 為例,下面我們來做一些優化,讓短期並發的負載下減少伺服器的真實請求。

Next.js API Route 的回應快取#

這是一個簡單的 Next.js API Route。

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export const GET = async (req: NextRequest) => {
  return NextResponse.json({})
}

現在我們可以增加快取標頭。

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export const GET = async (req: NextRequest) => {
  return NextResponse.json(
    {},
    {
      headers: {
        'Cache-Control': 'max-age=60, s-maxage=86400',
        'CDN-Cache-Control': 'max-age=86400',
      },
    },
  )
}

現在把 API 使用 Cloudflare 代理。

在第一次請求之後,下一次請求中,我們能看到 Cloudflare 命中了快取。

Cf-Cache-Status: HIT

使用 vercel.json 全局配置標頭#

在單個 API 中,每每的添加快取標頭非常的麻煩並且我們也無法控制除了 API Route 之外的其他路由。我們可以使用 vercel.json 全局配置標頭。

在項目根目錄下新建 vercel.json,內容如下:

下面路由參考項目 Shiro,可按需配置路由。

{
  "headers": [
    {
      "source": "/",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "s-maxage=300, stale-while-revalidate=59"
        },
        {
          "key": "CDN-Cache-Control",
          "value": "max-age=300"
        },
        {
          "key": "Vercel-CDN-Cache-Control",
          "value": "max-age=300"
        }
      ]
    },
    {
      "source": "/og",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "s-maxage=3600, stale-while-revalidate=30"
        },
        {
          "key": "CDN-Cache-Control",
          "value": "max-age=3600"
        },
        {
          "key": "Vercel-CDN-Cache-Control",
          "value": "max-age=3600"
        }
      ]
    },
    {
      "source": "/api/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "s-maxage=60, stale-while-revalidate=30"
        },
        {
          "key": "CDN-Cache-Control",
          "value": "max-age=60"
        },
        {
          "key": "Vercel-CDN-Cache-Control",
          "value": "max-age=60"
        }
      ]
    },
    {
      "source": "/feed",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "s-maxage=86400, stale-while-revalidate=3600"
        },
        {
          "key": "CDN-Cache-Control",
          "value": "max-age=86400"
        },
        {
          "key": "Vercel-CDN-Cache-Control",
          "value": "max-age=86400"
        }
      ]
    }
  ]
}

使用 Vercel 提供的配置,可以對每個路由進行快取標頭的配置。配置過後,Vercel 會在回應這些請求時,自動添加快取標頭,然後經過 Cloudflare 讀取快取標頭,然後在 Cloudflare 網路進行快取,在下次請求到達時,直接從 Cloudflare 快取中讀取。

stale-while-revalidate= 的值控制了一個資源在過期後,多久內仍然可以使用過期資源,然後在後台異步更新資源,那麼在即便過期的場景下,用戶也能快速的獲取到資源,加快頁面加載。

[!IMPORTANT]

路由的匹配是從下到上的,那麼也就是說,第一項可以定義為全局 Fallback 也就是路由匹配 /(.*)

參考:https://vercel.com/docs/projects/project-configuration#headers

Vercel 邊緣網快取#

你可能也注意到 Vercel-CDN-Cache-Control 這個標頭。這個標頭是 Vercel 私有的標頭,用來控制資源在 Vercel 邊緣網路的快取。既然 Vercel 也提供了快取,為什麼還要使用 Cloudflare 呢?

我想大概有下面的原因:

  1. Cloudflare 一般作為 DNS 提供商,他會有著更加快速的回應時間。
  2. Vercel 的快取命中很奇怪,有時候會命中,有時候不會命中,讓我跟費解;而 Cloudflare 的快取命中符合文檔,在意料之中。

此文由 Mix Space 同步更新至 xLog 原始鏈接為 https://innei.in/posts/tech/vercel-cloudflare-http-header-about-cache

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。