核心概念与术语:FaaS、BaaS、冷启动、无状态设计、事件驱动、按需付费模型
好,咱们正式开始聊 Serverless 的核心概念。说实话,很多新手一上来就被这些术语搞懵了。什么 FaaS、BaaS,听着像绕口令。别急,我一个一个给你拆开讲。这些概念搞懂了,后面整个架构设计你就通了。
FaaS:函数即服务
FaaS 是 Serverless 的基石。说白了,就是把你的代码打包成一个函数,扔到云上跑。你不用管服务器,不用管操作系统,甚至不用管运行时环境。
我在项目中遇到过最典型的场景:用户上传图片后,自动生成缩略图。以前我得搭个图片处理服务,部署到服务器上,还得考虑并发。用 FaaS 呢?写个函数,绑定到对象存储的事件上,完事。
核心特征:
- 代码以函数粒度部署
- 由事件触发执行
- 执行完即销毁
- 按调用次数和时长计费
// 一个典型的 FaaS 函数(Node.js 示例)
exports.handler = async (event) => {
// event 里包含了触发事件的所有信息
const imageUrl = event.Records[0].s3.object.key;
// 处理逻辑
const thumbnail = await generateThumbnail(imageUrl);
return {
statusCode: 200,
body: JSON.stringify({ thumbnailUrl: thumbnail })
};
};
你想想看,这种模式最大的好处是什么?弹性伸缩。来了 100 个请求,自动拉起 100 个实例。没人访问时,一个实例都没有。零成本闲置。
BaaS:后端即服务
BaaS 是 FaaS 的好搭档。它提供了一堆现成的后端能力:数据库、认证、存储、消息队列等等。你不需要自己搭建这些基础设施。
我个人习惯把 BaaS 理解为「乐高积木」。你需要用户登录?直接调认证 API。需要存数据?调数据库 API。需要发消息?调消息队列 API。
我的经验: 刚开始用 BaaS 时,我总担心被厂商锁定。后来想通了——业务跑起来比什么都重要。真有迁移需求时,加个适配层就行了。
| BaaS 服务 | 典型产品 | 解决的问题 |
|---|---|---|
| 用户认证 | Auth0, AWS Cognito | 注册、登录、权限管理 |
| 数据库 | Firebase, DynamoDB | 数据存储与查询 |
| 对象存储 | S3, OSS | 文件上传、下载、CDN |
| 消息队列 | SQS, Pub/Sub | 异步通信、削峰填谷 |
冷启动:躲不开的坑
冷启动是 Serverless 最让人头疼的问题。为什么会这样?因为函数实例不是一直活着的。当请求来了,平台得先拉起一个容器,加载你的代码,初始化运行时环境,然后才能执行。
我曾经踩过一个坑:一个金融交易系统的风控函数,冷启动耗时 3 秒。用户等不了啊。后来怎么解决的?用了预留并发 + 定时预热。
避坑指南: 我曾经天真地以为所有函数都能接受冷启动。直到线上出了事故才明白——对延迟敏感的业务,必须做预热策略。比如支付回调、实时推荐这些场景,冷启动就是灾难。
冷启动的典型耗时分布:
- 容器启动:100-300ms
- 运行时初始化:200-500ms
- 代码加载:100-200ms
- 业务初始化:取决于你的代码
嗯,这里要注意:Java 和 .NET 的冷启动比 Node.js、Python 慢得多。选语言时得权衡一下。
无状态设计:Serverless 的命根子
无状态设计,说白了就是函数不保存任何本地状态。每次调用都是全新的环境。你上次写入的临时文件,这次调用时已经没了。
我刚开始做 Serverless 时犯过一个低级错误:把用户会话信息存在函数的内存里。结果用户第二次请求时,被路由到了另一个实例,会话丢了。用户直接掉线。
正确的做法:
- 状态存到外部存储(Redis、数据库)
- 文件存到对象存储(S3、OSS)
- 会话信息用 JWT 或分布式缓存
- 日志直接打到集中式日志系统
// ❌ 错误示范:依赖本地状态
let userSession = {};
exports.handler = async (event) => {
userSession[event.userId] = event.data;
// 下次调用时,userSession 可能已经没了
};
// ✅ 正确示范:使用外部存储
const redis = require('redis');
const client = redis.createClient();
exports.handler = async (event) => {
await client.set(event.userId, JSON.stringify(event.data));
// 状态持久化,任何实例都能访问
};
事件驱动:一切皆事件
Serverless 是事件驱动的。什么意思?函数不是主动运行的,而是被事件触发的。文件上传了、数据库变了、消息队列来了新消息——这些都是事件。
你想想看,这种模式天然适合异步处理。用户下单 -> 触发订单处理函数 -> 触发库存更新函数 -> 触发通知函数。整个链路像流水线一样自动流转。
我的建议: 设计事件驱动架构时,一定要考虑事件幂等性。同一个事件被处理两次,结果应该一样。我在项目中就用过事件去重表,效果很好。
常见的事件源:
- HTTP 请求(API Gateway)
- 数据库变更(CDC)
- 文件上传/删除
- 定时任务(Cron)
- 消息队列消息
- IoT 设备数据
按需付费模型:省钱还是烧钱?
按需付费是 Serverless 最大的卖点。你只为实际使用的资源付费,不为闲置资源买单。听起来很美好,对吧?
但我要泼点冷水:这个模型不是所有场景都省钱。我见过一个团队,把高频调用的 API 也迁到了 Serverless,结果账单比原来还高。为什么?因为每次调用都要计费,高频场景下累积起来很可观。
避坑指南: 我曾经帮一个客户优化 Serverless 成本。发现他们有个函数每秒被调用 1000 次,每次执行 500ms。算下来一个月光这个函数就花了 2 万美金。后来改成常驻服务,成本降了 80%。
| 场景 | Serverless 成本 | 传统服务器成本 | 推荐方案 |
|---|---|---|---|
| 低频调用(每天几百次) | 极低 | 高(服务器闲置) | Serverless |
| 高频调用(每秒上千次) | 高 | 低(资源复用) | 传统服务 |
| 突发流量 | 按需付费 | 需预留资源 | Serverless |
| 稳定负载 | 偏高 | 最优 | 传统服务 |
说白了,按需付费模型最适合「间歇性、突发性、不可预测」的工作负载。如果你的流量像心跳一样规律,那传统服务器反而更划算。
好了,这六个核心概念讲完了。它们之间是相互关联的:FaaS 提供计算能力,BaaS 提供后端服务,冷启动是性能瓶颈,无状态设计是架构约束,事件驱动是触发机制,按需付费是经济模型。搞懂这些,你就掌握了 Serverless 的底层逻辑。