#DevOps

Serverless 架构实践

Serverless 让你只管写代码、不管服务器,但它的无状态/冷启动/计费模型带来新约束。本文讲清 Serverless 的核心(FaaS + BaaS)、适用场景(事件驱动/突发/低流量)、代价(冷启动/供应商锁定/调试难),以及什么该用、什么不该用。

本文要点

  • 主题聚焦:DevOps
  • 适合人群:独立开发者、全栈工程师、AI 应用开发者
  • 核心价值:快速理解背景、实践路径、常见误区和工程建议
作者 @admin·发布于 2026年4月28日·更新于 2026年7月23日

我帮一个创业团队把一个内部工具从 ECS 迁到 Lambda,部署那天老板看完账单直呼"真香"——从每个月 800 块的常驻实例,掉到一个月 30 块按调用计费。两周后业务上线,真正的考验来了:第一次请求总是慢个两三秒,数据库连接数莫名其妙被打爆,本地怎么都复现不了线上那个偶发 bug。这篇文章把 Serverless 的核心、优势、代价一次讲透,让你在"上车"前就知道哪里有坑。

一、Serverless 到底是什么:FaaS + BaaS

很多人把 Serverless 等同于"云函数",这只说对了一半。Serverless 是两层组合:

  • FaaS(Function as a Service,函数即服务):你写一个函数,云厂商负责把它跑起来、伸缩、计费。AWS Lambda、Vercel Functions、Cloudflare Workers、阿里云函数计算都属于这一类。你不碰服务器,甚至不碰进程,只管"事件进来 → 函数跑 → 返回"。
  • BaaS(Backend as a Service,后端即服务):把数据库、对象存储、认证、消息队列这些后端能力变成托管的 API。Supabase、Firebase、DynamoDB、S3、Cognito 都是 BaaS。

真正的"无服务器",是 FaaS 负责跑你的代码、BaaS 负责扛状态和存储,两边都按用量计费、都自动伸缩。本质变化只有一个:你不再为"机器"付费,而是为"执行"付费。没有流量的时候,函数根本不存在实例,计费归零——这是它和传统云主机最大的区别。

一句话:Serverless 不是没有服务器,是服务器不再是你操心的事。

二、它真正的优势:免运维、按需付费、自动伸缩

Serverless 不是银弹,但它解决的三件事是实打实的:

  1. 免运维:没有机器要打补丁、没有操作系统要升级、没有 SSH 进不去的凌晨三点。安全更新、容量规划、可用区分布全是云厂商的事。对一个三五个人的小团队,这省下来的是一个专职 SRE 的工资。
  2. 按需付费:传统实例 7×24 跑着,半夜没流量也在烧钱。Serverless 按"请求数 × 执行时长 × 内存"计费,没流量不花钱。一个一天才几十次访问的后台 API,迁过去账单能砍一个数量级。
  3. 自动伸缩(含缩到零):流量从 1 RPS 涨到 10000 RPS,云厂商自动并发起函数实例;流量退下去,实例自动回收。不需要写 HPA、不需要预留 buffer、也不需要为"万一火了"提前买机器。

这三点叠加,让 Serverless 成为低流量、突发流量、事件驱动场景的性价比之王。

三、代价:冷启动、时长限制、无状态、锁定、调试难

优势的另一面是五条硬约束,每一条都够你喝一壶:

  • 冷启动:函数空闲一段时间被回收,下一个请求进来要重新拉镜像、起运行时、加载代码。Node/Python 通常几百毫秒,Java/JVM 动辄几秒。这就是开头那个"第一次请求慢两三秒"的根因。冷启动是 Serverless 的原罪,优化方向只有几个:精简依赖、缩小打包体积、用 provisioned concurrency 预热、选更轻的运行时。
  • 执行时长限制:Lambda 单次最多 15 分钟,Vercel 默认 10 秒(可升到 5 分钟、流式到 800K 上下文)。长任务根本塞不进一个函数,视频转码、大批量数据处理得切片或者改用 Step Functions / 队列 + worker。
  • 无状态:每次调用可能落在不同实例,函数内的全局变量、内存缓存、本地文件不能跨请求信赖。状态必须外移到 Redis、DB、对象存储。习惯了常驻进程里 const cache = new Map() 的人,这里会反复翻车。
  • 供应商锁定:从 Lambda 迁到 Cloudflare,不是改个 SDK 就完事——触发器、IAM、事件格式、部署工具全是厂商私有的。上了 Serverless 就要做好"换厂商成本很高"的心理预期,把业务逻辑和厂商 SDK 隔离干净是唯一缓解手段。
  • 调试和本地开发难:serverless-offline 之类的工具只能模拟个大概,IAM 权限、触发器联动、网络配置在本地几乎复现不了。线上排查要靠 CloudWatch / 日志,链路一长就抓瞎,分布式追踪(Trace)在 Serverless 里不是可选项,是必需品。

四、什么时候该用:事件驱动、突发、低频、API 后端

代价讲清楚了,但 Serverless 在这几类场景里几乎是默认答案:

  • 事件驱动:webhook 回调、S3 上传后生成缩略图、CodePush 推送后触发构建、Stripe 收款后写流水。事件来了跑一下,跑完就消失,这正是 FaaS 的天然形态,用常驻服务去等一个一小时一次的事件才是浪费。
  • 定时任务:每天凌晨跑一次数据汇总、每小时清理一次过期 session。cron 触发一个函数,比养一台 cron 机器干净得多。
  • 突发流量:秒杀、营销活动、推文带量。Serverless 自动伸缩,扛得住瞬时高峰,活动结束自动缩到零,不用为 5 分钟的流量买一天的机器。
  • 低频低流量:内部后台、管理工具、Demo 环境。一天没几次访问,按调用计费比常驻实例便宜一个数量级。
  • API 后端:配合 Next.js / SvelteKit 这类全栈框架,Vercel / Netlify 把每个 API route 编译成函数,前端静态、后端函数,一栈到底。

五、什么时候别用:长连接、常驻、低延迟、重计算

反过来,这几类场景上 Serverless 就是自找麻烦:

  • 长连接(WebSocket / SSE / gRPC streaming):函数是请求-响应模型,跑完就退,撑不住长连接。要做实时推送要么用专门的托管服务( API Gateway WebSocket、Pusher、Ably ),要么老老实实常驻服务。
  • 常驻服务:消费 Kafka 的 worker、订阅 Redis pub/sub 的 listener、维护内存态的聊天网关——这些必须进程不死,和"跑完就退"的函数模型天然冲突。
  • 高稳定低延迟:冷启动的几百毫秒到几秒抖动,在 P99 SLA 要求 50ms 的核心交易系统里不可接受。
  • 重计算:机器学习训练、大规模视频转码、批处理 ETL。时长限制和计费模型会让账单比租 GPU 实例还贵,且根本跑不完。

判断标准很简单:这个服务"必须一直在线"吗?是,就别用 Serverless。

六、数据库连接:Serverless 的经典翻车点

这是几乎所有团队迁 Serverless 都会踩的坑,值得单独拎出来。

传统应用一个常驻进程持有一个连接池(20 条连接),复用一辈子。Serverless 不一样:每个函数实例是独立短命进程,并发一起来,云厂商瞬间开出几百个实例,每个都新建一条 DB 连接。PostgreSQL 这种进程模型的数据库,200 条连接就能把它内存吃光、max_connections 直接打爆。表现就是:FATAL: too many connections、连接超时、数据库 OOM。

解决方案有两条路:

text
方案 A:在 DB 前面加连接池中间件(PgBouncer)
  [ Lambda ×N ] ──> [ PgBouncer (transaction mode) ] ──> [ PostgreSQL ]
                       复用少量连接,抗住瞬时并发

方案 B:用原生 Serverless 数据库
  [ Function ] ──> [ Neon / PlanetScale / Aurora Serverless ]
                    HTTP API 或连接池内置,按存储和计算计费
  • 方案 A:自建 PG 前面挂 PgBouncer,开 transaction pooling 模式,把几百条短连接复用成十几条到 DB 的长连接。注意 transaction 模式下不能用 prepared statements、session-level advisory lock,Prisma 要开 ?pgbouncer=true。
  • 方案 B:直接用 Neon、PlanetScale、Aurora Serverless v2 这类为 Serverless 设计的数据库——它们要么提供 HTTP 接口(连接即 HTTP 请求),要么内置池化,还能"缩到零"省钱。新项目这条路最省心。

一句话:Serverless + 传统直连 DB = 必炸。函数短命,就得给 DB 配池化,或干脆用 Serverless 原生 DB。

七、典型架构:函数 + 静态前端 + 托管 DB

把上面拼起来,这就是当下最主流的轻量现代栈:

text
                    ┌──────────────────────────┐
   用户 ──── CDN ──▶│  静态前端                 │
                    │  (Next.js SSG/SSR on Vercel)│
                    └─────────────┬────────────┘
                                  │ API 调用(函数)
                                  ▼
                    ┌──────────────────────────┐
                    │  Serverless Functions     │  ◀── webhook / cron 触发
                    │  (认证、业务、文件处理)   │
                    └───┬────────────┬──────────┘
                        │            │
              ┌─────────▼───┐  ┌─────▼────────┐
              │ Serverless  │  │ 对象存储 S3   │
              │ DB (Neon)   │  │ / R2          │
              └─────────────┘  └──────────────┘

前端静态化上 CDN(Next.js 的 SSG/ISR 部署在 Vercel / Cloudflare Pages),业务逻辑编译成函数,数据放托管 DB,大文件放对象存储。全栈按用量计费、自动伸缩、缩到零。一个 MVP 用这套,从上线到月活破万,基础设施成本可能就没超过一杯咖啡。这套最适合独立开发者、创业团队、内部工具。

八、别 all-in:混合架构才是正解

最后一条,也是我见过最多团队栽跟头的地方:别 all-in Serverless。

Serverless 的甜区很明确,边界也很硬。一个像样的生产系统,通常是混合架构:核心交易、长连接、重计算用常驻服务(K8s / ECS / 裸机),边缘的、事件驱动的、突发的、低频的用 Serverless。比如电商:订单核心服务常驻,保证 P99 低延迟和长连接;图片缩略、对账邮件、定时报表、秒杀限流这些用函数;前端静态化上 CDN。各司其职,不要用一把锤子敲所有钉子。

判断一个组件该用哪种,问三个问题:它需要一直在线吗?(要→常驻)它的流量是突发的吗?(是→Serverless)它的延迟要求严苛吗?(严→常驻)。三个问题答完,选型基本就定了。

小结

  • Serverless = FaaS(跑代码)+ BaaS(扛状态/存储),核心变化是按"执行"付费而非按"机器"付费。没流量不花钱、自动伸缩到零,是它对低频和事件驱动场景的杀手锏。
  • 五条硬约束必须先认账:冷启动、执行时长限制、无状态、供应商锁定、调试难。优势不是免费的,它是用这几条约束换来的。
  • 甜区是事件驱动(webhook/cron/文件处理)、突发流量、低频低流量、API 后端;雷区是长连接、常驻服务、严苛低延迟、重计算——"必须一直在线"的就别用。
  • DB 连接是经典翻车点:函数短命会瞬间打爆直连 DB。要么前面挂 PgBouncer 做 transaction 池化,要么换 Neon / PlanetScale 这类 Serverless 原生 DB。
  • 典型轻量栈:静态前端(CDN)+ Serverless 函数 + 托管 DB + 对象存储,但生产系统应该是混合架构——核心常驻、边缘 Serverless,各司其职。

一句话收尾:Serverless 不是把服务器藏起来,是把"什么时候该操心服务器"这件事交给了你——选对场景它便宜到离谱,选错场景它贵到离谱还慢。

Related

相关推荐