☁️ 托管方案:VPS / Container / Serverless / Edge

你的代码写好了,现在让它跑起来——选择正确的托管方式,比优化代码更重要
📑 目录

概述:四种托管范式

托管方案的选择本质上是控制权 vs 便利性的权衡。你掌控越多,运维负担越重;你交给平台越多,灵活性越受限。

🎮 控制权光谱
VPS (全控) 容器 (中控) Serverless (少控) Edge (零控)

左→右:运维负担递减,灵活度递减

💰 成本模型光谱
固定成本 (VPS) 混合 (容器) 按量计费 (Serverless/Edge)

固定成本可预测,按量计费弹性高

💡 核心原则:早期选最简单的方案验证想法,用户增长后再优化成本。过早优化托管架构是 SaaS 死亡率 Top 5 的原因之一。

VPS / 云服务器

是什么

虚拟专用服务器——你获得一台(虚拟的)Linux 机器,拥有 root 权限,可以安装任何软件、运行任何进程。这是最传统也最灵活的托管方式。

主流提供商与定价

提供商入门价/月特色适合场景
Hetzner Cloud €3.29 (2vCPU/2GB) 欧洲性价比之王,ARM 实例更便宜 成本敏感、欧洲用户
腾讯云轻量 ¥34 (2vCPU/2GB) 国内合规,CN2 GIA 线路,带宽包 中国用户、需要备案
AWS EC2 $3.5-7 (t3.micro) 生态最全,Spot 实例可省 90% 需要 AWS 全家桶
DigitalOcean $4 (512MB) / $6 (1GB) 开发者友好,文档优秀,Droplet 简单 个人项目、小团队
Vultr $2.5 (512MB) 32 个机房,按小时计费,高频实例 全球分布、短期任务
Linode(Akamai) $5 (1GB) 稳定可靠,新 Nanode 系列 长期稳定运行
Oracle Cloud 免费 (4ARM/24GB) Always Free 层极其大方,ARM 性能好 免费实验、低流量服务

实际部署示例:Hetzner Cloud + Docker

# 1. 安装 hcloud CLI
brew install hcloud  # 或: curl ... | bash

# 2. 创建服务器 (最便宜的 CX22)
hcloud server create \
  --name my-saas \
  --type cx22 \
  --image ubuntu-24.04 \
  --location fsn1

# 3. SSH 登录并安装 Docker
ssh root@<IP>
curl -fsSL https://get.docker.com | sh
docker swarm init  # 单节点 Swarm,后续可扩展

# 4. 部署应用
docker compose up -d

# 5. 配置防火墙 (hcloud CLI)
hcloud firewall create --name my-firewall --rules-file firewall.json
hcloud firewall apply-to-server my-firewall my-saas

自动化 Provisioning:用 Terraform 管理

# main.tf - Hetzner Cloud
terraform {
  required_providers {
    hcloud = { source = "hetznercloud/hcloud" }
  }
}

variable "hcloud_token" { sensitive = true }

provider "hcloud" { token = var.hcloud_token }

resource "hcloud_server" "web" {
  name        = "saas-prod"
  server_type = "cx22"           # €3.29/月
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = [hcloud_ssh_key.default.id]

  # 启动后自动安装 Docker
  user_data = file("cloud-init.yaml")
}

resource "hcloud_ssh_key" "default" {
  name       = "admin"
  public_key = file("~/.ssh/id_ed25519.pub")
}

output "ip" { value = hcloud_server.web.ipv4_address }
# cloud-init.yaml
#cloud-config
packages:
  - docker.io
  - docker-compose-plugin
  - nginx
  - certbot
  - python3-certbot-nginx

runcmd:
  - systemctl enable docker
  - usermod -aG docker ubuntu
  - ufw allow 22/tcp
  - ufw allow 80/tcp
  - ufw allow 443/tcp
  - ufw --force enable

优劣对比

✅ 优势
  • 完全控制——想装什么装什么
  • 成本可预测——月费固定
  • 无厂商锁定——Linux 就是 Linux
  • 可以跑任何服务:数据库、Redis、后台任务
  • Hetzner/Oracle Free Tier 性价比碾压
  • 学习曲线低——就是 SSH + Linux
❌ 劣势
  • 运维全靠你——安全补丁、备份、监控
  • 扩展性差——手动加机器或配负载均衡
  • 单点故障——一台机器挂了服务就停了
  • 带宽成本高(尤其 AWS/GCP)
  • 冷启动慢——不是按需自动启动
  • 安全责任在你——防火墙、SSH 硬化

VPS 安全加固清单

#!/bin/bash
# vps-harden.sh — 新 VPS 必做安全加固

# 1. 更新系统
apt update && apt upgrade -y

# 2. 创建非 root 用户
adduser deploy
usermod -aG sudo deploy

# 3. SSH 加固
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd

# 4. 防火墙
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

# 5. 自动安全更新
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

# 6. Fail2ban 防暴力破解
apt install -y fail2ban
systemctl enable fail2ban

# 7. 安装 Docker
curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy
⚠️ VPS 最大的坑:忘记备份。用 restic + S3 做自动备份,或用云厂商的快照功能。数据丢了就什么都没了。

容器托管 (Container-as-a-Service)

是什么

你只需提供 Docker 镜像(或 Dockerfile),平台负责构建、部署、扩缩、负载均衡。你仍然控制容器内的环境,但不再管理底层服务器。

主流平台

平台计费特色入门成本/月
Fly.io 按 VM 运行时间 全球边缘部署、自动 WireGuard 内网、Postgres 内置 免费层 → ~$5
Railway 按 vCPU/GB-ram/GB-disk 用量 GitHub 一键部署、开发环境友好、数据库即服务 $5-20
Render 按实例时间 PR Preview 环境、Cron Jobs、自动 SSL 免费层 → $7
Google Cloud Run 按请求数 + CPU/内存时间 缩到零、IAM 集成、Cloud SQL 直连 免费层 → $10
AWS App Runner 按 vCPU/GB 时间 VPC 接入、自动扩缩、从 ECR/GitHub 部署 $7+
Azure Container Apps 按 vCPU/GB + 请求 K8s 底层、Dapr 集成、缩到零 免费层 → $10
Coolify 自托管免费 开源 PaaS、自建 Heroku 替代品 VPS 费用 (€3.29)

实战:Fly.io 部署 Next.js + Postgres

# 1. 安装 Fly CLI
curl -L https://fly.io/install.sh | sh

# 2. 登录
fly auth login

# 3. 初始化项目
fly launch  # 自动检测 Next.js,生成 fly.toml + Dockerfile

# 4. 创建 Postgres 数据库
fly postgres create
fly postgres attach <db-name>

# 5. 设置环境变量
fly secrets set NEXTAUTH_SECRET=$(openssl rand -hex 32)
fly secrets set DATABASE_URL=<auto-from-attach>

# 6. 部署!
fly deploy

# 7. 扩展到多区域
fly regions add nrt  # 东京
fly regions add sin  # 新加坡
# fly.toml — Fly.io 配置文件
app = "my-saas"
primary_region = "sjc"

[build]
  dockerfile = "Dockerfile"

[env]
  PORT = "3000"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = "stop"
  auto_start_machines = true
  min_machines_running = 1    # 保持 1 台热启动

[checks]
  [checks.alive]
    type = "http"
    port = 3000
    path = "/api/health"
    interval = "10s"
    timeout = "5s"

实战:Coolify 自托管 PaaS (VPS 上跑)

# 在 Hetzner VPS (€3.29/月) 上安装 Coolify
# 这给你一个 Heroku 级别的 PaaS,但只花 VPS 的钱

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

# 安装后访问 http://<IP>:8000
# 然后通过 Web 界面:
# 1. 连接 GitHub 仓库
# 2. 自动检测 Dockerfile / nixpacks
# 3. 一键部署
# 4. 自动 SSL (Let's Encrypt)
# 5. 数据库一键创建 (PostgreSQL/MySQL/Redis/MongoDB)
# 6. 支持多个项目/服务

# Coolify 优势:
# - 完全开源 (Apache 2.0)
# - 无厂商锁定 (标准 Docker)
# - 成本 = VPS 价格
# - 支持多台服务器
# - 自动备份

优劣对比

✅ 优势
  • 比 VPS 少 80% 的运维工作
  • 自动扩缩容(Fly/Cloud Run 可缩到零)
  • 内置 SSL、负载均衡、健康检查
  • 多区域部署只需一行命令 (Fly.io)
  • 标准 Docker 镜像,迁移成本低
  • Coolify 让你在 VPS 上获得 PaaS 体验
❌ 劣势
  • 比纯 VPS 贵 2-5x (Fly/Railway)
  • 冷启动延迟(缩到零后的首次请求)
  • 持久存储受限(大多数是 ephemeral)
  • 调试困难——你不能 SSH 进去看
  • 平台限制(内存上限、请求超时)
  • 厂商锁定程度中等
💡 Coolify 是 2024-2026 年最值得关注的自托管方案:在 €3.29/月的 Hetzner VPS 上跑 Coolify,你获得 Railway 级别的体验,但成本只有 1/5。适合 MVP 和早期用户阶段。

Serverless / FaaS (Function-as-a-Service)

是什么

你只写函数,平台负责一切:从 HTTP 请求到函数执行的完整链路。函数只在请求到来时运行,按实际执行时间计费。没有服务器要管理,没有进程要守护。

主流平台

平台运行时冷启动免费层特色
AWS Lambda Node/Python/Java/Go/.NET 100ms-5s (视 runtime) 100万请求/月 最成熟、VPC、Layer、Provisioned Concurrency
Vercel Node/Edge(JS) 50-250ms 10万请求/天 Next.js 一等公民、Preview 部署、Edge Runtime
Netlify Functions Node/Go 200-500ms 12.5万请求/月 静态站点 + 函数一体、表单处理
Cloudflare Workers V8 Isolate (JS/WASM) <5ms (几乎无冷启动) 10万请求/天 全球 300+ PoP、KV/D1/R2 生态、超快
Deno Deploy TS/JS/WASM <10ms 100万请求/月 全球边缘、原生 TS、零配置
Supabase Edge Functions Deno (TS) <50ms 50万调用/月 与 Supabase DB/Auth 深度集成

实战:Cloudflare Workers + Hono (API 服务)

// src/index.ts — Cloudflare Worker API
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { jwt } from 'hono/jwt'

type Bindings = {
  DB: D1Database
  JWT_SECRET: string
}

const app = new Hono<{ Bindings: Bindings }>()

// 全局中间件
app.use('/*', cors())

// 公开路由
app.get('/api/health', (c) => c.json({ status: 'ok' }))

app.post('/api/auth/login', async (c) => {
  const { email, password } = await c.req.json()
  const user = await c.env.DB.prepare(
    'SELECT * FROM users WHERE email = ?'
  ).bind(email).first()

  if (!user) return c.json({ error: 'Not found' }, 404)

  // 验证密码...
  return c.json({ token: 'jwt-token-here' })
})

// 受保护路由
app.use('/api/*', jwt({ secret: 'JWT_SECRET' }))

app.get('/api/projects', async (c) => {
  const { results } = await c.env.DB.prepare(
    'SELECT * FROM projects WHERE user_id = ?'
  ).bind(c.get('jwtPayload').sub).all()

  return c.json(results)
})

export default app
# wrangler.toml — Cloudflare Workers 配置
name = "my-saas-api"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[[d1_databases]]
binding = "DB"
database_name = "my-saas-db"
database_id = "xxx-xxx-xxx"

[vars]
JWT_SECRET = "change-me-in-secrets"

# 部署
# wrangler d1 create my-saas-db
# wrangler d1 migrations apply my-saas-db
# wrangler deploy

实战:Vercel Serverless + Next.js App Router

// app/api/webhooks/stripe/route.ts
import { headers } from 'next/headers'
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)

export async function POST(req: Request) {
  const body = await req.text()
  const sig = headers().get('stripe-signature')!

  try {
    const event = stripe.webhooks.constructEvent(
      body, sig, process.env.STRIPE_WEBHOOK_SECRET!
    )

    switch (event.type) {
      case 'checkout.session.completed':
        // 处理支付成功
        const session = event.data.object
        await handleCheckoutComplete(session)
        break
      case 'customer.subscription.updated':
        // 处理订阅变更
        await handleSubscriptionUpdate(event.data.object)
        break
    }

    return Response.json({ received: true })
  } catch {
    return Response.json({ error: 'Invalid signature' }, { status: 400 })
  }
}

Serverless 冷启动深度解析

🥶 冷启动是怎么回事?

Serverless 函数在没有请求时会被平台回收。当新请求到来时,平台需要:

  1. 分配容器/运行时 — 创建执行环境 (50-200ms)
  2. 加载代码 — 从存储加载你的函数代码 (50-500ms)
  3. 初始化 — 执行全局作用域代码、连接数据库 (100ms-5s)
  4. 处理请求 — 实际执行你的函数 (通常 <100ms)

关键优化:数据库连接用连接池管理器(如 Prisma Accelerate、Supabase Pooler),避免冷启动时建立新连接。

冷启动优化策略

// 1. 保持函数精简 — 减小 bundle size
// next.config.js
module.exports = {
  experimental: {
    serverComponentsExternalPackages: ['sharp'],  // 排除大依赖
  },
}

// 2. 全局缓存 — 在函数初始化时预加载
let dbClient: PrismaClient | null = null

function getDb() {
  if (!dbClient) {
    dbClient = new PrismaClient({
      datasourceUrl: process.env.DATABASE_URL_POOL, // 用 pooler URL
    })
  }
  return dbClient
}

// 3. Provisioned Concurrency (AWS Lambda) — 保持实例热
// serverless.yml
functions:
  api:
    handler: handler.main
    provisionedConcurrency: 2  # 始终保持 2 个热实例,$14/月额外

// 4. Vercel Edge Runtime — 消除冷启动
// app/api/fast/route.ts
export const runtime = 'edge'  // V8 isolate,<5ms 冷启动
export async function GET() {
  return Response.json({ hello: 'world' })
}

优劣对比

✅ 优势
  • 零运维——不用管服务器
  • 按量计费——没流量不花钱
  • 自动扩缩——1 请求到 10000 请求无需配置
  • 极速部署——vercel deploy 几秒上线
  • Preview 环境——每个 PR 自动生成预览
  • Cloudflare Workers 几乎无冷启动
❌ 劣势
  • 冷启动延迟(Lambda 可达 5s)
  • 执行时间限制(Lambda 15min, Workers 30s)
  • 本地开发体验差(需模拟器)
  • 厂商锁定严重(Vercel/Cloudflare 特有 API)
  • 调试困难——日志分散、难复现
  • 长连接/WebSocket 支持有限
  • 高流量时成本可能超 VPS 10x

Edge / 边缘计算

是什么

把代码部署到全球数百个节点(Point of Presence),用户的请求被路由到最近的节点执行。不是"发到美国处理再返回",而是"在用户旁边处理"。延迟从 200ms+ 降到 10ms。

主流平台

平台节点数运行时存储计费
Cloudflare Workers 300+ V8 Isolate (JS/WASM) KV/D1/R2/Hyperdrive 请求 + CPU 时间
Vercel Edge 100+ V8 Isolate (JS) Edge Config/KV 包含在 Pro 计划
Deno Deploy 35+ V8 Isolate (TS/JS/WASM) KV/Queue 请求
Fly.io (Edge) 35+ 完整 Docker Volumes/Postgres VM 运行时间
Fastly Compute 80+ WASM (Rust/JS/Go) KV/Object Store 请求 + CPU

实战:Cloudflare Workers 全栈 SaaS

// 完整的边缘 SaaS 架构
// 
// 架构:
//   用户 → Cloudflare CDN (最近的 PoP) 
//        → Worker (处理请求)
//        → D1 (SQL 数据库,只读副本就近)
//        → R2 (对象存储,兼容 S3)
//        → KV (全局键值,配置/特征开关)

// wrangler.toml
name = "edge-saas"
main = "src/index.ts"

[[d1_databases]]
binding = "DB"
database_name = "edge-saas"
database_id = "xxx"

[[r2_buckets]]
binding = "STORAGE"
bucket_name = "user-uploads"

[[kv_namespaces]]
binding = "CONFIG"
id = "xxx"

[vars]
ENVIRONMENT = "production"
// src/index.ts — 边缘 API
import { Hono } from 'hono'

type Env = {
  DB: D1Database
  STORAGE: R2Bucket
  CONFIG: KVNamespace
  STRIPE_KEY: string
}

const app = new Hono<{ Bindings: Env }>()

// A/B 测试 — 用 KV 在边缘做分流
app.get('/', async (c) => {
  const variant = Math.random() > 0.5 ? 'A' : 'B'
  const config = await c.env.CONFIG.get(`landing:${variant}`, 'json')

  return c.html(renderLanding(config))
})

// 就近读取 — D1 自动路由到最近副本
app.get('/api/products', async (c) => {
  const cacheKey = new Request(c.req.url, c.req)
  const cache = caches.default

  // 先查 CDN 缓存
  let response = await cache.match(cacheKey)
  if (response) return response

  // 缓存未命中,查 D1
  const { results } = await c.env.DB.prepare(
    'SELECT * FROM products WHERE active = 1 ORDER BY created_at DESC LIMIT 50'
  ).all()

  response = Response.json(results, {
    headers: { 'Cache-Control': 'public, max-age=60' },
  })

  // 写入边缘缓存
  c.executionCtx.waitUntil(cache.put(cacheKey, response.clone()))

  return response
})

// 文件上传 — 直接到 R2
app.post('/api/upload', async (c) => {
  const formData = await c.req.formData()
  const file = formData.get('file') as File

  const key = `uploads/${crypto.randomUUID()}/${file.name}`
  await c.env.STORAGE.put(key, file.stream())

  return c.json({ key, url: `/api/files/${key}` })
})

export default app

Edge 的限制与应对

⚠️ Edge 运行时不是 Node.js

Edge Runtime 基于 V8 Isolate,不是完整的 Node.js 进程。以下功能不可用

应对:runtime = 'nodejs' 跑重任务,runtime = 'edge' 只用于延迟敏感的路由(认证检查、A/B 测试、特征开关、缓存读取)。

优劣对比

✅ 优势
  • 超低延迟——全球 10-30ms 响应
  • 几乎无冷启动(V8 Isolate <5ms)
  • 内置 DDoS 防护(Cloudflare 级别)
  • 自动全球分布——无需配置多区域
  • 完美适合 API 网关、BFF、认证检查
  • Cloudflare 免费层极其慷慨
❌ 劣势
  • 运行时限制——不是完整 Node.js
  • 存储复杂——D1/KV 最终一致
  • 不适合 CPU 密集任务
  • 厂商锁定严重
  • 调试困难——日志分散在全球节点
  • 数据库延迟——边缘计算快,但 DB 可能在远方

成本深度对比

场景 1:MVP 阶段 (0-1K 用户)

方案月成本包含备注
Hetzner VPS €3.29 (≈$3.6) 2vCPU/2GB/40GB 需自建一切,成本最低
Oracle Free Tier $0 4ARM/24GB/200GB 免费,但资源不保证
VPS + Coolify €3.29 (≈$3.6) VPS + PaaS 体验 ⭐ 最佳性价比 MVP 方案
Railway $5-15 App + DB + Redis 开发体验最好
Vercel Pro $20 无限部署 + Edge 如果重度用 Next.js
Cloudflare Workers $0-5 10万请求/天 + D1 免费层够用

场景 2:增长阶段 (1K-50K 用户)

方案月成本架构备注
2x Hetzner VPS €6.58 (≈$7.2) App + DB 分离 手动负载均衡
Fly.io $15-40 2 App + Postgres + Redis 自动扩缩、多区域
Railway $30-80 按用量自动扩 容易超预算
AWS (EC2+RDS+ALB) $40-80 EC2 t3.small + RDS + ALB 企业级但贵
Vercel + Supabase $25-60 Vercel Pro + Supabase Pro 全 Serverless 栈

场景 3:规模化阶段 (50K+ 用户)

方案月成本架构备注
Hetzner 集群 €20-50 (≈$22-55) 3 App + 1 DB + LB 成本仍然很低
K8s on Hetzner €30-80 K3s 集群 + Rook/Ceph 需要 K8s 运维知识
Fly.io $50-200 多区域 + 大 DB 扩展到全球最方便
AWS 全家桶 $200-1000+ EKS + RDS + ElastiCache + ... 贵但稳定,企业首选
混合架构 $50-300 VPS(重任务) + Edge(API) + Serverless(事件) ⭐ 成本和性能的甜点

成本可视化:$100/月你能跑什么

💲 $100/月 预算分配示例
Hetzner App ×2
€6.58
Hetzner DB
€9.22
Cloudflare Pro
$20
S3/R2 存储
$5
Vercel Pro
$20
Supabase Pro
$25
剩余 Buffer
≈$13

这个配置可以支撑 5-10 万用户级别的 SaaS

决策框架:何时选什么

🎯 30 秒决策树
你需要什么?
│
├─ "我只想让我的应用跑起来" ─→ VPS + Coolify (€3.29/月)
│
├─ "我要最少的运维" ─→ Vercel / Railway ($5-20/月)
│
├─ "我的用户在全球各地" ─→ Fly.io 或 Cloudflare Workers
│
├─ "我需要跑重型后台任务" ─→ VPS (Hetzner/腾讯云)
│
├─ "我要最便宜" ─→ Oracle Free Tier ($0) 或 Hetzner (€3.29)
│
├─ "我要中国市场" ─→ 腾讯云/阿里云 (必须备案)
│
└─ "我已经有用户在增长" ─→ 混合架构 (见下文)
  

按项目阶段的推荐

🧪 概念验证 (0 用户)

推荐:Cloudflare Workers (免费) 或 Vercel Free

目标:验证想法,不花钱

Workers Free Vercel Free Oracle Free

🚀 MVP (0-1K 用户)

推荐:VPS + Coolify 或 Railway

目标:快速上线,控制成本

Hetzner+Coolify Railway Fly.io

📈 增长期 (1K-50K)

推荐:Fly.io 多区域 或 VPS 集群

目标:可靠 + 可扩展

Fly.io 2-3x VPS 混合架构

按技术栈的推荐

技术栈最佳托管原因避免
Next.js Vercel 一等公民支持、ISR、Edge Runtime 自己配 Next.js 在 VPS 上很痛苦
Remix / Hono Fly.io / Cloudflare Workers 标准 Web API,边缘优先 AWS Lambda (过重)
Django / FastAPI VPS / Fly.io 需要持久进程、后台任务 Vercel/Workers (Python 支持弱)
Go / Rust 服务 Fly.io / VPS 单二进制、低资源、高并发 Lambda (启动开销大)
AI/ML 推理 VPS with GPU / Replicate 需要 GPU、长运行时间 Serverless (超时/无 GPU)

混合架构实战

现实中的 SaaS 不是纯 VPS 或纯 Serverless——而是组合使用,每种工作负载用最适合的托管方式。

推荐混合架构 (2025-2026)

混合架构拓扑
🌐 Cloudflare CDN ⚡ Workers (认证/路由/AB测试)
🖥️ VPS (API + Worker) 📄 Vercel (Next.js 前端)
🐘 Supabase / Postgres 📦 R2 / S3 (文件存储)

实战配置

# 混合架构实现 — 以 SaaS 订阅产品为例

# ━━━━━━ 层 1: Cloudflare (DNS + CDN + Edge) ━━━━━━
# Cloudflare Dashboard:
# 1. DNS 指向 Vercel (前端) 和 VPS (API)
# 2. Workers 处理:
#    - 认证检查 (JWT 验证在边缘)
#    - A/B 测试 (KV 存储变体)
#    - 速率限制
#    - 缓存 API 响应

# ━━━━━━ 层 2: Vercel (Next.js 前端) ━━━━━━
# vercel.json
{
  "rewrites": [
    { "source": "/api/(.*)", "destination": "https://api.mysaas.com/$1" }
  ]
}
# 前端 + SSR + ISR 在 Vercel
# API 调用代理到 VPS

# ━━━━━━ 层 3: VPS (API + 后台任务) ━━━━━━
# docker-compose.yml on Hetzner VPS
services:
  api:
    build: .
    ports: ["3001:3001"]
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - REDIS_URL=redis://redis:6379
    deploy:
      resources:
        limits:
          memory: 1G

  worker:
    build: .
    command: node dist/worker.js
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - REDIS_URL=redis://redis:6379
    deploy:
      resources:
        limits:
          memory: 512M

  redis:
    image: redis:7-alpine
    volumes: ["redis-data:/data"]

  # Stripe Webhook 接收
  stripe-wh:
    build: .
    command: node dist/stripe-webhook.js
    ports: ["3002:3002"]

volumes:
  redis-data:

# ━━━━━━ 层 4: 数据 ━━━━━━
# Supabase (托管的 Postgres + Auth + Storage)
# 或者自建 Postgres 在 VPS 上

每月成本估算

组件提供商月费说明
DNS + CDN + Edge Cloudflare Free/Pro $0-20 免费层够 MVP 用
前端 SSR Vercel Pro $20 Next.js 最佳搭档
API + Worker Hetzner CX22 €3.29 2vCPU/2GB 足够跑 API
数据库 Supabase Pro $25 或自建 Postgres (€0)
文件存储 Cloudflare R2 $0-5 10GB 免费,无出口费
邮件 Resend $0-20 3千封/月免费
总计 $48-93 可支撑 5 万用户

迁移策略

随着 SaaS 增长,托管方案必然需要升级。以下是常见的迁移路径和注意事项。

常见迁移路径

典型 SaaS 托管演进路线
Phase 0: Vercel Free / Workers Free
↓ 验证 PMF
Phase 1: VPS + Coolify (€3.29/月)
↓ 首批付费用户
Phase 2: 混合架构 ($50-100/月)
↓ 用户快速增长
Phase 3: K8s / 多区域 ($200+/月)

迁移时的数据迁移

# 从 SQLite → PostgreSQL 迁移示例
# (常见于从 VPS 单机 → 托管数据库)

# 1. 用 pgloader 一键迁移
# 安装
apt install pgloader

# 执行迁移
pgloader sqlite:///path/to/app.db \
  postgresql://user:pass@host:5432/mydb

# 2. 或者用 Prisma 迁移
npx prisma migrate diff \
  --from-schema-datasource prisma/schema.prisma \
  --to-schema-datamodel prisma/schema.prisma \
  --script > migration.sql

# 3. 零停机迁移策略
# a) 双写:新代码同时写旧 DB 和新 DB
# b) 验证:对比两边数据一致性
# c) 切换:读取切到新 DB
# d) 清理:停止写旧 DB

# 4. 回滚方案
# 保留旧 DB 7 天,只读模式
# 发现问题立即切回

迁移 Checklist

📋 迁移前必查项

如果你在构建 AI Agent 产品(参考 Agent 架构研究),托管方案有特殊要求:

🤖 Agent 托管的特殊需求

1. 长时间运行

Agent 任务可能运行几分钟到几小时。Serverless 有执行时间限制(Lambda 15 分钟),所以 Agent Worker 必须跑在 VPS/容器上

# Agent Worker 部署方案
# docker-compose.yml
services:
  agent-worker:
    build: .
    command: node dist/agent-worker.js
    environment:
      - REDIS_URL=redis://redis:6379
      - LLM_API_KEY=${LLM_API_KEY}
    # 无时间限制,直到任务完成
    # 用 BullMQ/Inngest 管理任务队列

2. SSE / 流式响应

Agent 回复需要流式输出。Vercel Serverless 支持 SSE(但有限制),VPS 最灵活。

// Next.js Route Handler — 流式 Agent 响应
export async function POST(req: Request) {
  const encoder = new TextEncoder()
  const stream = new ReadableStream({
    async start(controller) {
      // 调用 Agent,逐 token 输出
      for await (const chunk of agent.run(prompt)) {
        controller.enqueue(
          encoder.encode(`data: ${JSON.stringify({ text: chunk })}\n\n`)
        )
      }
      controller.enqueue(encoder.encode('data: [DONE]\n\n'))
      controller.close()
    }
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
    }
  })
}

3. 沙箱执行

Agent 执行代码需要沙箱。参考 安全机制——OpenHands 用 Docker 容器隔离,SWE-agent 用 Bundle 脚本。

4. 推荐架构

# AI Agent 产品推荐托管架构
#
# ┌─────────────┐     ┌──────────────┐     ┌──────────────┐
# │   Vercel    │     │  Hetzner VPS │     │  Cloudflare  │
# │  (前端 SSR) │────▶│  (API +      │────▶│  Workers     │
# │             │     │   Agent 工人) │     │  (认证/路由)  │
# └─────────────┘     └──────┬───────┘     └──────────────┘
#                            │
#                     ┌──────▼───────┐
#                     │  Supabase    │
#                     │  (Postgres + │
#                     │   Auth)      │
#                     └──────────────┘

替代方案速查

需求首选平替不推荐
最便宜的 VPS Hetzner Cloud Oracle Free / 腾讯云轻量 AWS EC2 (太贵)
开发者体验最好 Railway Vercel / Render 裸 VPS (需自建)
全球低延迟 Cloudflare Workers Fly.io / Deno Deploy 单区域 VPS
中国市场 腾讯云/阿里云 华为云 境外 VPS (需备案)
AI/ML 推理 Replicate / Together AI GPU VPS (Lambda Labs) Serverless (无 GPU)
自托管 PaaS Coolify Dokku / CapRover 裸 Docker Compose
K8s 托管 GKE Autopilot EKS / AKS 自建 K8s (除非你有 SRE)

关键链接

🔗 VPS 提供商
🔗 PaaS / Serverless
🔗 自托管工具
🔗 知识库内链