3. Serverless 集群概念

在进入生产部署之前,必须建立对 Serverless 集群核心概念的共识。本章将围绕集群定义、FaaS 与 BaaS 的职责划分、事件驱动架构的运行机制以及冷启动与热启动的性能差异展开,为后续的集群搭建与部署实践打下理论基础。

3.1 集群定义:从单函数到分布式集群

Serverless 集群并非指传统的虚拟机或容器集群,而是一个由 函数运行时、事件源、后端服务(BaaS)和调度层 组成的分布式执行环境。集群的核心职责是:

  • 弹性调度:根据请求量自动扩缩函数实例。
  • 资源隔离:每个函数运行在独立的沙箱或容器中。
  • 高可用:跨可用区部署,避免单点故障。
  • 统一观测:提供日志、指标、链路追踪能力。
维度 传统集群(K8s) Serverless 集群
最小调度单元 Pod / 容器 函数实例(Function Instance)
扩缩容粒度 分钟级(HPA) 毫秒级(每请求)
运维责任 用户管理节点、网络、存储 平台托管,用户只关注代码
计费模式 按资源预留(包月/按量) 按实际调用次数与执行时长
关键认知: Serverless 集群的本质是“逻辑集群”,物理资源由云平台统一调度,用户感知不到底层节点。集群的边界由函数命名空间、VPC 配置和事件源绑定关系定义。

3.2 FaaS 与 BaaS:职责分离

Serverless 架构由两大核心组件构成:函数即服务(FaaS) 和 后端即服务(BaaS)。理解二者的分工是设计 Serverless 应用的前提。

  • FaaS(函数即服务):负责执行业务逻辑,以函数为单位部署,无状态、事件驱动、自动扩缩。例如:处理 HTTP 请求、消费消息队列、执行定时任务。
  • BaaS(后端即服务):提供托管的后端能力,函数通过 SDK 或 API 调用。例如:对象存储、数据库、身份认证、消息队列。
最佳实践: 函数内不要直接管理数据库连接池或文件系统,这些职责应交给 BaaS。函数只做“胶水代码”——编排 BaaS 服务并返回结果。
FaaS 与 BaaS 协作架构 FaaS 与 BaaS 协作架构 事件源 HTTP 网关 消息队列 对象存储事件 定时触发器 数据库变更流 FaaS 层 函数 A(订单处理) 函数 B(图片转码) 函数 C(数据聚合) 函数 D(通知推送) 无状态 · 自动扩缩 按调用计费 BaaS 层 对象存储(OSS) 数据库(RDS / DynamoDB) 消息队列(MQ) 身份认证(IAM) 日志与监控 托管服务 · 按量付费

3.3 事件驱动架构

Serverless 集群天然是事件驱动的。事件驱动架构(EDA)包含三个核心角色:事件生产者、事件通道、事件消费者(函数)。函数不主动监听端口,而是由事件源通过触发器调用。

常见事件源与触发器

事件源 触发器类型 典型场景
API 网关 HTTP / HTTPS RESTful API、WebSocket
消息队列 Kafka / RabbitMQ / SQS 异步任务、削峰填谷
对象存储 上传 / 删除事件 图片处理、视频转码
定时器 Cron 表达式 数据备份、报表生成
数据库变更 CDC(变更数据捕获) 缓存刷新、搜索索引同步
避坑提示: 事件驱动架构中,函数必须设计为幂等。同一事件可能因重试机制被多次投递,非幂等函数会导致数据重复或状态不一致。
事件驱动架构流程 事件驱动架构流程 事件生产者 事件通道 消息队列 / 事件总线 触发器 函数调用 函数 业务逻辑 异步回调 / 结果投递到下一个事件源

3.4 冷启动与热启动

冷启动是 Serverless 集群中最影响性能的机制之一。理解冷热启动的差异,对函数设计、内存配置和预置并发策略至关重要。

冷启动(Cold Start)

当函数实例在空闲一段时间后被回收,或首次被调用时,平台需要重新分配沙箱、加载运行时、初始化代码。这个过程称为冷启动,通常耗时 100ms ~ 10s,取决于运行时和依赖包大小。

热启动(Warm Start)

当函数实例仍驻留在内存中,平台直接复用已有沙箱执行请求。热启动延迟通常在 1ms ~ 10ms 级别,几乎无感知。

对比维度 冷启动 热启动
触发条件 实例回收后首次调用 / 新版本部署 实例存活期间连续调用
延迟 100ms ~ 10s 1ms ~ 10ms
资源开销 高(分配沙箱 + 加载依赖) 极低(复用上下文)
影响因素 运行时类型、代码包大小、初始化逻辑 实例保持活跃的时间窗口
优化手段 预置并发、精简依赖、延迟初始化 保持最小活跃实例数
优化策略:
  • 预置并发(Provisioned Concurrency):提前初始化指定数量的实例,消除冷启动。
  • 代码瘦身:移除不必要的依赖,使用轻量运行时(如 Node.js 对比 Java)。
  • 全局变量复用:将数据库连接、配置加载放在函数初始化阶段(全局作用域),而非每次请求内。
  • Keep-Alive 策略:通过定时器或健康检查请求保持实例活跃。

冷启动时间分布示例

阶段 耗时(典型值) 说明
沙箱分配 20ms ~ 200ms 容器或微虚拟机启动
运行时加载 50ms ~ 500ms Node.js / Python / Java 运行时初始化
代码下载 10ms ~ 2s 从对象存储拉取函数包
全局初始化 10ms ~ 5s 数据库连接、配置加载、依赖注入
函数执行 取决于业务 实际业务逻辑耗时
生产建议: 对于延迟敏感的场景(如 API 网关在线服务),务必启用预置并发,并将函数内存配置在 512MB 以上(内存越高,CPU 分配越多,冷启动越快)。对于离线任务(如消息队列处理),冷启动通常可接受,无需额外成本。