Serverless 单兵作战:独立开发者的云端架构路线

Serverless 单兵作战:独立开发者的云端架构路线

前言

去年我朋友找我合作一个项目。他负责产品设计,我负责全栈开发。他问我:你的服务器在哪?我说:我没有服务器。他愣了一下------没有服务器怎么做产品?

我说的是真的。我的所有产品都跑在 Serverless 架构上,没有一台我需要自己维护的服务器。从用户注册、支付、AI 推理到定时任务,全部是"按需付费"的模式。

这篇文章就讲讲我作为"单兵作战"的独立开发者,怎么用 Serverless 架构撑起整套产品基础设施。

一、核心机制:单兵作战的云端架构设计

1.1 架构总览

graph TD A["用户浏览器"] --> B["Vercel Edge Network"] B --> C["Next.js App"] C --> D["Vercel Functions"] D --> E["Stripe 支付"] D --> F["OpenAI API"] D --> G["Supabase 数据库"] D --> H["Vercel KV"] C --> I["静态资源 CDN"] style A fill:#6366f1,color:#fff style D fill:#10b981,color:#fff

整个架构的核心思想是:每一个组件都是托管服务,我只管调用,不管维护。

1.2 各层选型决策

层级 选型 作为独立开发者的选择理由
前端托管 Vercel 免费套餐够用,自动 HTTPS,全球 CDN
后端计算 Vercel Functions 零配置,按调用计费,自动扩缩容
数据库 Supabase 免费额度慷慨,支持实时订阅
缓存 Vercel KV 基于 Redis,API 简洁
文件存储 Supabase Storage 与数据库同一平台
AI 能力 OpenAI API 无需 GPU,按 token 付费
支付 Stripe 开发者体验最好,文档优秀
域名 Cloudflare DNS 免费,配置简单

这个架构每月的基础开销是 0 元------直到产品开始有用户。

二、核心实现:搭建单兵云端架构

2.1 项目初始化

typescript 复制代码
// 用 create-next-app 初始化项目
// npx create-next-app@latest my-project --typescript --tailwind --app

// 安装依赖
// npm install @supabase/supabase-js @vercel/kv stripe openai

2.2 数据库层:Supabase

typescript 复制代码
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY;

export const supabase = createClient(supabaseUrl, supabaseKey);

用 Supabase 的 Row Level Security 做权限控制,不需要自己写中间件:

sql 复制代码
-- 只允许用户查看自己的数据
CREATE POLICY "用户只能看自己的数据" ON 项目
  FOR SELECT
  USING (auth.uid() = 用户ID);

-- 只有付费用户才能创建超过 3 个项目
CREATE POLICY "付费用户可创建更多项目" ON 项目
  FOR INSERT
  WITH CHECK (
    auth.uid() = 用户ID
    AND (
      (SELECT 订阅状态 FROM 用户 WHERE id = auth.uid()) = 'pro'
      OR (SELECT COUNT(*) FROM 项目 WHERE 用户ID = auth.uid()) < 3
    )
  );

2.3 缓存层:Vercel KV

typescript 复制代码
// lib/cache.ts
import { createClient } from '@vercel/kv';

const kv = createClient({
  url: process.env.KV_REST_API_URL,
  token: process.env.KV_REST_API_TOKEN,
});

export async function 缓存获取<T>(key: string, 获取函数: () => Promise<T>, ttl = 300): Promise<T> {
  const 缓存 = await kv.get(key);
  if (缓存) return JSON.parse(缓存);

  const 数据 = await 获取函数();
  await kv.set(key, JSON.stringify(数据), { ex: ttl });
  return 数据;
}

// 使用示例
const 热门文章 = await 缓存获取('hot-articles', async () => {
  const { data } = await supabase.from('文章').select('*').order('阅读量', { ascending: false }).limit(10);
  return data;
}, 600);

2.4 API 层:Serverless Functions

typescript 复制代码
// app/api/articles/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { supabase } from '@/lib/supabase';
import { 缓存获取 } from '@/lib/cache';

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const 页码 = parseInt(searchParams.get('page') || '1');
  const 每页 = parseInt(searchParams.get('limit') || '20');

  const 数据 = await 缓存获取(`articles:${页码}:${每页}`, async () => {
    const { data, count } = await supabase
      .from('文章')
      .select('*', { count: 'exact' })
      .range((页码 - 1) * 每页, 页码 * 每页 - 1)
      .order('创建时间', { ascending: false });

    return { 数据: data, 总数: count };
  });

  return NextResponse.json(数据);
}

export async function POST(req: NextRequest) {
  const 文章 = await req.json();

  const { data, error } = await supabase
    .from('文章')
    .insert({
      标题: 文章.标题,
      内容: 文章.内容,
      用户ID: 文章.用户ID,
    })
    .select()
    .single();

  if (error) {
    return NextResponse.json({ error: error.message }, { status: 400 });
  }

  return NextResponse.json(data, { status: 201 });
}

2.5 定时任务:Vercel Cron

typescript 复制代码
// app/api/cron/daily-digest/route.ts
import { NextResponse } from 'next/server';

export const runtime = 'nodejs';

export async function GET() {
  // 每天早上 8 点给用户发送日报
  const 活跃用户 = await 获取昨日活跃用户();

  for (const 用户 of 活跃用户) {
    const 日报数据 = await 生成日报(用户.id);
    await 发送邮件(用户.邮箱, '你的每日摘要', 日报数据);
  }

  return NextResponse.json({ 发送数: 活跃用户.length });
}

// vercel.json 配置
// {
//   "crons": [
//     {
//       "path": "/api/cron/daily-digest",
//       "schedule": "0 8 * * *"
//     }
//   ]
// }

三、单兵作战的经验

3.1 三个"不"原则

原则 说明 我的做法
不自己管服务器 任何需要 SSH 登录的场景都尽量避免 全部用托管服务
不自己搭基础组件 用户系统、支付、数据库都是现成的 用 Clerk / Supabase / Stripe
不重复造轮子 有成熟方案就不自己写 先用开源,再按需定制

3.2 成本管理的技巧

Serverless 的按量付费对独立开发者友好,但也有陷阱:

  • 数据库连接数:Supabase 免费版最多 10 个连接。如果函数并发太多可能不够用。解决方案是加一层缓存。
  • 函数调用次数:Vercel 免费版每月 100k 次调用。个人项目通常用不完。
  • KV 存储:按存储量计费,缓存记得设过期时间。

四、总结

独立开发者的核心优势是灵活性------别人需要三周才能完成的流程,我三天就能跑通,靠的就是 Serverless 架构的零摩擦。

你可以把这套架构看作一条"云端流水线":写代码、部署、上线、迭代。每一环都有对应的托管服务帮你在跑,你要做的就是把它们串起来。

一个人就是一支队伍------关键在于不要让基础设施的复杂度拖慢你的迭代速度

相关推荐
zhangfeng11331 小时前
Megatron-LM(英伟达超大模型训练框架)完整介绍和DeepSpeed 类似
人工智能
hixiong1231 小时前
C# Tokenizers.DotNet测试工具
开发语言·人工智能·llm
Cosolar1 小时前
LlamaIndex 索引类型进阶:构建高性能 RAG 系统的核心能力
人工智能·开源·全栈
人工智能AI技术2 小时前
【VibeCoding系列教程11】 AI智能体平台
人工智能
wing982 小时前
我的AI编程体验:从白嫖到付费,我为什么最终留下了Codex
前端·人工智能·程序员
YOLO数据集集合2 小时前
智慧林业无人机巡检 松材线虫病害树木实例分割数据集 | 森林枯木识别 深度学习视觉
人工智能·深度学习·目标检测·计算机视觉·无人机
听你说322 小时前
深耕具身智能,亿达科创智能四足仿生机器人亮相沈阳机器人大会
人工智能·机器人
前端的阶梯2 小时前
Cursor 开发 Python 项目完全指南
前端·人工智能·后端
Linlingu2 小时前
OpenClaw接入阿里云百炼模型配置教程(完整可落地)
人工智能·阿里云·云计算·办公自动化·数字员工·小龙虾