1.4 Serverless 的两种形态:FaaS 与 BaaS


1.4 Serverless 的两种形态:FaaS 与 BaaS

本节摘要:Serverless 不是一项单一技术,而是 FaaS(函数即服务)和 BaaS(后端即服务)的组合。FaaS 负责跑你的业务逻辑,BaaS 负责提供数据库、存储、认证这些后端能力。本节讲清两者的职责边界、协作方式,并给出最小代码示例。

学习目标

阅读完本节,你应当能够:

  1. 用一句话区分 FaaS 和 BaaS
  2. 说出 FaaS 函数的入口结构(事件、上下文、返回值)
  3. 列出 BaaS 常见的服务类别
  4. 理解一个 Serverless 应用如何由 FaaS + BaaS 拼成

一、先划清职责

很多人把 Serverless 等同于 FaaS,这是不完整的。一个真实的 Serverless 应用,几乎一定是 FaaS + BaaS 的组合:

  • FaaS(函数即服务):承载你的业务逻辑。你写一段函数,上传,平台在事件来时跑它。它是"计算"那部分。
  • BaaS(后端即服务):提供后端能力——数据库、对象存储、认证、消息队列、API 网关。你不用自己搭这些服务,直接调用云厂商托管的。它是"能力"那部分。

打个比方:FaaS 是"后厨厨师"(接到订单才炒菜,炒完歇着),BaaS 是"食材库、冰箱、收银台"(厨师要用就去取)。光有厨师没食材做不出菜,光有食材没厨师也没人做。一个 Serverless 应用就是"厨师 + 一整套后厨设施"。

架构示意

下面这张图展示了一个典型 Serverless 应用的三层结构:事件源触发 FaaS 函数,函数调用各种 BaaS 服务完成业务。

架构示意

事件从顶部进来触发函数,函数在中间跑业务逻辑,需要存数据、做认证时调用底层的 BaaS 服务。注意函数本身是无状态的,所有持久化都靠 BaaS。

二、FaaS:函数的入口长什么样

不管哪家云厂商,FaaS 函数的入口结构都高度相似:接收一个事件(event)和一个上下文(context),返回一个响应。

import json def handler(event, context): # event: 触发这次执行的事件数据(HTTP 请求的参数、上传文件的信息等) # context: 运行时上下文(函数名、内存限制、剩余执行时间等) return { "statusCode": 200, "body": json.dumps({"message": "Hello, Serverless!"}), }

这段 Python 是典型的 FaaS 函数骨架。handler 是入口,平台在事件来时调用它;event 告诉你"发生了什么",context 告诉你"在什么环境下跑";返回值是一个结构化响应(HTTP 场景下是状态码 + 响应体)。

💡 关键直觉:FaaS 函数永远是"被叫起来 → 干活 → 返回 → 歇着"这个循环。它不是常驻服务,所以别在函数里放while循环等请求,也别指望上次的变量还在——每次都可能是个全新实例。

三、BaaS:现成的后端能力

BaaS 把你过去要自己搭的后端服务做成了托管 API。常见的几类:

BaaS 类别 典型服务 用来干嘛
数据库 DynamoDB、Firestore、CosmosDB 存业务数据,无需自建数据库
对象存储 S3、OSS、COS 存文件、图片、备份
认证 Cognito、Firebase Auth 用户注册登录、Token 管理
消息队列 SQS、Pub/Sub 异步解耦、削峰
API 网关 API Gateway 把 HTTP 请求路由到函数
事件总线 EventBridge、Event Grid 跨服务事件分发

用 BaaS 的好处是你不用运维这些组件,坏处是又一层厂商绑定。下面是一段调用 BaaS(Firebase 认证)的最小示例,感受一下"前端直接用托管后端"是什么样:

import { getAuth, signInWithEmailAndPassword } from "firebase/auth"; function login(email, password) { signInWithEmailAndPassword(getAuth(), email, password) .then(cred => console.log("登录成功", cred.user)) .catch(err => console.error("登录失败", err.code)); }

注意这里前端代码直接调了托管的认证服务,没有一个自己写的后端进程——这就是 BaaS 的典型用法。

四、FaaS + BaaS 怎么拼成一个应用

把两者拼起来,一个完整的 Serverless 应用大致是这个样子:

客户端请求打到 API 网关(BaaS),网关触发函数 A,A 读写数据库(BaaS)并把耗时任务丢进消息队列(BaaS);队列再触发函数 B 去异步处理,结果落到对象存储。整条链路里没有一个你需要运维的服务器。

⚠️ 设计要点:函数之间不要直接互相调用(那会变成同步串行,丢失弹性),而是通过事件/消息来解耦。让"事件"在函数之间流转,而不是"调用"。

五、FaaS 与 BaaS 的分工是怎么演化出来的

FaaS 和 BaaS 这对组合并非同时降生,它们的分工是在实践里逐渐磨合出来的,这段历史能帮你看懂今天边界的位置。

FaaS 先出现。早期函数平台只有"跑代码"这一件事,开发者很快发现不够用:数据存哪?没有常驻进程就没有本地文件;用户怎么登录?没有会话内存。第一批实践者的做法很朴素——函数里连传统数据库。问题随之而来:每次冷启动都要重新建立数据库连接,高并发下函数实例潮涌般各自建连,把数据库的连接数瞬间打爆。这个痛点直接催生了第一批"Serverless 原生"的 BaaS:面向 HTTP 的 API 模式数据库、按请求计费、连接由平台侧的代理统一管理。BaaS 的很多设计细节,只有放在"FaaS 的约束"这个背景下才能读懂——它们不是随便托管的旧服务,而是为函数的使用模式重新设计的服务。

另一个演化方向是"计算与能力的边界"。最初认证服务要靠函数调用 SDK 完成,后来厂商把认证做成了网关层的直接能力——请求到网关时先验 Token,验不过根本不触发函数。这个变化把"认证"从函数的职责里彻底拿走了。同样的模式一再重演:限流、缓存、协议转换,凡是能标准化的工作都在从函数下沉到平台。预测这条线的走向很有价值:今天写在函数里的逻辑,明天可能就变成平台的一个开关。 保持函数"薄"、把标准化工作尽量交给 BaaS 配置,不仅省代码,也让你自动吃到平台演化的红利。

六、动手感受:一个最小的"缩略图生成器"

概念讲完,用一个三步的最小场景把 FaaS + BaaS 的协作手感建立起来。目标:用户上传图片后自动生成缩略图。

第一步,配置对象存储(BaaS)的事件通知:新图片写入指定目录时,触发你的函数。第二步,写函数(FaaS):入口的 event 里带着新文件的名字和位置,函数下载图片、用图像库缩小、把结果写回另一个目录。第三步,配置权限:给函数授权读写这两个目录。完成后整条链路是"上传即出缩略图",中间没有任何服务器。

def handler(event, context): bucket = event["bucket"] key = event["object"] # 例如 photos/original/cat.jpg raw = download(bucket, key) # 从对象存储下载原图 thumb = resize(raw, width=200) # 概念示意:图像缩放 upload(bucket, "photos/thumb/" + key, thumb) return {"thumb": "photos/thumb/" + key}

注意代码之外的三件事,它们才是 Serverless 的本体:你配置了触发器(存储事件到函数的绑定)、配置了权限(函数能碰哪些资源)、写了一个无状态的处理函数。代码三十行不到,运维量为零,且一年没人传图就一年零费用——这正是"短、频、变"场景的完整体验。第 4 章的开发全流程,会把这三件事展开成工程级的完整清单。

💡 延伸思考:如果同一张图要生成三种尺寸,你会写三个函数还是一个函数处理三次事件?先自己想,再看第 2 章事件驱动架构一节的讨论——答案和"事件该怎么设计"直接相关。

本节要点回顾

  • Serverless = FaaS(业务逻辑)+ BaaS(后端能力),二者缺一不可。
  • FaaS 函数入口:接收 event + context,返回结构化响应;无状态、事件驱动。
  • BaaS 提供数据库、存储、认证、消息队列、网关等托管能力。
  • 架构三层:事件源 → FaaS 函数 → BaaS 服务
  • 设计上让事件在函数间流转,避免函数直接互调,保住弹性。

到这里第 1 章的概览就结束了。下一章我们会钻进 FaaS、BaaS、事件驱动这三个核心概念的内部机理。

五、形态组合的三个经典配方

FaaS 与 BaaS 的组合在实践中沉淀出几个经典配方,值得记熟。配方一,静态站加函数后端:静态资源放对象存储加 CDN,动态请求进函数,数据库用托管服务——个人项目与内容型网站的最省配置,月成本可以低到忽略不计。配方二,事件管道:上传触发缩略图函数、消息触发通知函数、定时触发报表函数——每个函数只做一件小事,用队列与总线串成流水线,这是媒体处理与数据摄取场景的标准形态。配方三,API 编排层:函数做轻量的聚合与鉴权,重查询下推给托管查询服务——移动端后台的常见骨架,函数层保持薄,复杂度沉到 BaaS。三个配方的共同智慧:函数保持小而傻,状态与重活交给 BaaS——这是 Serverless 架构的第一设计原则,违反它(在函数里养状态、在函数里跑重计算)的项目,会把两种形态的缺点集于一身。配方思维的价值是给新手提供经过验证的起点——先照配方做,理解了每味料的存在理由,再谈自创。

再展开一个新手常见误区:把 BaaS 当数据库的同义词——BaaS 是一个大得多的版图(认证、消息、对象存储、搜索、监控告警……),数据库只是其中一类;更重要的是选型视角的差异:选数据库你比较的是性能与功能,选 BaaS 你比较的是"外包出去的复杂度与收回的主权"——第 2 章的四项核查(数据主权、配额、一致性、可观测)就是为这个视角准备的。带着"我在外包什么"的意识浏览 BaaS 目录,每个服务的取舍自然清晰;把它当功能超市随便拿,账单与锁定会迟到但不会缺席。

补一个两者边界的判断口诀:"逻辑放函数、事实放服务"——业务规则与编排逻辑属于你写的部分(FaaS),数据与状态属于托管的部分(BaaS);拿不准某段职责放哪时问一句"它是不是事实"——是事实就找托管服务,是判断就留在函数里。这个口诀能解决八成的架构分界争论,剩下两成再靠第 2 章的四项核查细究。

再补一组数字感觉:一个典型 Serverless 应用的成本与复杂度分布,函数侧常常只占两三成(计算),BaaS 侧占七八成(存储、流量、消息)——这个分布解释了两件事:成本治理的主战场在 BaaS(第 5 章的账本重点),架构评审的重点在两者边界(职责放对位置)。把注意力按七三开分配,是与这个技术形态相匹配的精力管理。

补一个两者协作的时序常识:函数与 BaaS 的调用时延存在数量级差——函数内逻辑纳秒到微秒、一次 BaaS 调用毫秒到几十毫秒、一次冷启动几十到几百毫秒;所以函数代码的优化重点永远是"减少 BaaS 调用次数与合并请求"而不是雕琢本地逻辑(本地再快也快不过少调一次网络);这个时序感是性能直觉的地基,拿着它读任何优化文章都不会迷路。

最后一个学习建议:动手把第 4 章的图片流水线在自己选定的平台上搭一遍——纸上谈完两种形态的分工后,亲手把"函数读桶、处理、写桶、发事件"的链路跑通,形态边界会从概念变成肌肉记忆;学习架构的最短路径从来是画一遍再搭一遍,缺了后一遍,前一遍只是懂得。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U