在使用 Next.js(App Router + ISR)时,部署策略如果设计不当,很容易出现:

  • ISR 缓存错乱
  • buildId 不匹配
  • 静态资源 404
  • 无法快速回滚

本文介绍一种生产可用的蓝绿部署方案:

  • 不修改域名
  • 不修改 Nginx
  • 不重启 Worker
  • 秒级回滚
  • 支持灰度发布

一、整体架构

us-east.example.com 为例:

User
   ↓
Cloudflare (Worker 注入版本头)
   ↓
us-east.example.com
   ↓
OpenResty
   ↓
next-blue  :3001
next-green :3002

关键思想:

  • 外部域名固定
  • 内部运行两个版本
  • 通过 Header 决定流量走向
  • 蓝绿是流量槽位,而不是版本号

二、内部端口规划

推荐:

Blue  → 3001
Green → 3002

Docker 启动方式:

docker run -d -p 127.0.0.1:3001:3000 --name next-blue  next-image:blue
docker run -d -p 127.0.0.1:3002:3000 --name next-green next-image:green

注意:

  • 仅绑定 127.0.0.1
  • 不暴露公网
  • 所有流量由 OpenResty 统一代理

三、OpenResty 蓝绿配置

1️⃣ 使用 map 计算 backend

map $http_x_version $backend {
    default blue;
    green green;
}

含义:

  • 请求头 x-version: green → 走 green
  • 其他情况 → 默认 blue

2️⃣ 定义 upstream

upstream blue {
    server 127.0.0.1:3001;
}

upstream green {
    server 127.0.0.1:3002;
}

upstream 是后端服务器组定义。

当执行:

proxy_pass http://green;

Nginx 会将请求转发到 127.0.0.1:3002。


3️⃣ server 代理

server {
    listen 443 ssl;
    server_name us-east.example.com;

    location / {
        proxy_pass http://$backend;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

关键在:

proxy_pass http://$backend;

$backend 由 map 动态决定。


四、Cloudflare Worker 显式控制蓝绿

错误做法(不推荐):

const versionColor =
  versionKey === "2026-02-26" ? "green" : "blue"

问题:

  • 强耦合版本号
  • 每次发版要改代码
  • 回滚需要重新发布 Worker

✅ 正确做法:KV 显式存储当前颜色

KV 结构:

current_color = green

Worker 代码:

const versionColor =
  (await KV.get("current_color")) || "blue"

request = new Request(request, {
  headers: {
    ...Object.fromEntries(request.headers),
    "x-version": versionColor,
  },
})

发布流程变成:

部署 green
↓
KV 设置 current_color = green
↓
流量自动切换

回滚:

KV 改回 blue

无需改代码。


五、蓝绿与版本解耦

更工程化设计:

{
  "blue": "build-2026-02-20",
  "green": "build-2026-02-26",
  "current": "green"
}

说明:

  • blue / green 是固定流量槽位
  • 版本号只是绑定关系
  • current 决定当前流量走向

蓝绿不是版本。

蓝绿是“发布位置”。


六、完整发布流程

假设当前:

3001 (blue)  → 正在线上
3002 (green) → 空闲

发版流程:

  1. 构建新镜像
  2. 部署到 green (3002)
  3. 本地验证
  4. 修改 KV → current_color = green
  5. 全量流量切换
  6. 保留 blue 作为回滚

整个过程:

  • 无需重启 Nginx
  • 无需修改 Worker
  • 无需改域名

七、进阶:支持灰度发布

KV:

{
  "stable": "blue",
  "canary": "green",
  "ratio": 10
}

Worker:

const config = await KV.get("deploy_config", "json")

let versionColor = config.stable

if (Math.random() * 100 < config.ratio) {
  versionColor = config.canary
}

即可实现 10% 灰度。


八、为什么这种设计更优?

优势总结:

  • 版本与流量解耦
  • 发布无需改代码
  • 回滚秒级完成
  • 可扩展灰度发布
  • 结构清晰

核心思想:

代码不控制版本,配置控制流量。


九、总结

在 Cloudflare + Next.js ISR 场景下:

最佳蓝绿方案是:

  • 双容器运行
  • OpenResty 使用 map + upstream
  • Worker 注入 x-version
  • KV 显式控制当前颜色
  • 蓝绿与版本解耦

最终效果:

  • 零停机发布
  • 秒级回滚
  • 可灰度
  • 可扩展
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐