5.1 服务模型:IaaS / PaaS / FaaS
一句话
三者不是三代技术,而是把责任边界切在不同深度的三刀:IaaS 切在虚拟硬件,PaaS 切在运行时与部署单元,FaaS 切到单次函数调用;切得越深,你少管的越多、可控的越少,单价里含的「平台溢价」越高。
责任边界:一条线,三个位置
同一套业务,三种模型下你要接手的东西完全不同:
| 你负责 | IaaS | PaaS | FaaS |
|---|---|---|---|
| 机房、硬件、虚拟化 | 云 | 云 | 云 |
| 操作系统内核与补丁 | 你 | 云 | 云 |
| 运行时(JDK / Go / Python) | 你 | 云(版本可选) | 云(版本有限) |
| 依赖与系统库 | 你 | 你(构建进制品) | 你(打进层/包) |
| 进程生命周期、健康检查 | 你 | 平台(部分) | 平台 |
| 扩缩容决策 | 你 | 你(配规则)或平台 | 平台(到 0) |
| 容量规划与闲置成本 | 你 | 你(实例数) | 平台(按调用付费) |
| 网络、负载均衡、证书 | 你(安全组/自建 LB) | 平台(部分) | 平台 |
| 可观测性 | 你装 agent | 平台给日志/指标 | 只有平台暴露的那些 |
🔑 判断一个服务属于哪一层,只问一句:**内核补丁谁打、进程挂了谁拉起、扩容谁决定。**三个答案都在你手里是 IaaS;都在平台手里是 FaaS;中间那档是 PaaS。
托管 K8s(EKS / ACK / GKE)常被当成 PaaS 卖,但责任线其实在「节点」:控制面托管、数据面(节点内核、kubelet、CNI)仍是你的,所以它更接近 CaaS——比 IaaS 少管控制面,比 PaaS 多管内核。
一句话判据:三种模型的「用户视角」
| 模型 | 你拿到的东西 | 你的第一个动作 | 你不知道的事 |
|---|---|---|---|
| IaaS | 一台能 SSH 的机器 | 装运行时、写 systemd unit | 物理机在哪、邻居是谁 |
| PaaS | 一个部署单元(应用 + 运行时) | git push 或上传制品 | 跑在哪台机器、几台机器 |
| FaaS | 一个函数 + 触发器 | 写 handler、配事件源 | 进程什么时候起、起几个、跑多久 |
计费:三种完全不同的成本函数
| 模型 | 计费单位 | 闲置时 | 成本随什么涨 | 典型省钱手段 |
|---|---|---|---|---|
| IaaS | 实例 × 时长(秒/小时) | 照收 | 峰值规格 × 时长 | 预留/包年、竞价实例、右规格 |
| PaaS | 实例规格 × 时长(含平台溢价) | 照收 | 实例数 × 时长 | 自动伸缩、只开必要中间件 |
| FaaS | 调用次数 + GB-秒(内存 × 时长) | 为 0 | 调用量 × 单次时长 × 内存 | 降内存、缩时长、减少调用 |
FaaS 的月成本可以直接写出来:
月成本 = 调用次数 × (单次时长s × 内存GB × GB-秒单价 + 每次调用单价)
IaaS 的月成本则是:
月成本 = 峰值所需实例数 × 实例月单价 ← 注意是峰值,不是均值
这两个公式的差别只有一处,却决定了选型:FaaS 为均值付费,IaaS 为峰值付费。
算一笔账:决定胜负的是峰均比,不是 QPS
设定(单价为公开价目表的量级,用于比较结构,不是报价):每次调用 200ms;FaaS 按 $0.0000167/GB-秒 + $0.20/百万次;IaaS 1 vCPU / 2 GiB 按量 $31/月。两种负载画像各算一遍:
| 平均并发 | 峰均比 | IO 型(0.05 vCPU / 0.25 GiB)FaaS / IaaS | CPU 型(1 vCPU / 1.7 GiB)FaaS / IaaS |
|---|---|---|---|
| 10 | 10× | $136 / $403 | $771 / $3,100 |
| 100 | 10× | $1,358 / $3,875 | $7,709 / $31,000 |
| 1000 | 10× | $13,578 / $38,750 | $77,088 / $310,000 |
| 10 | 2× | $136 / $93 | $771 / $620 |
| 100 | 2× | $1,358 / $775 | $7,709 / $6,200 |
| 1000 | 2× | $13,578 / $7,750 | $77,088 / $62,000 |
| 100 | 1.1× | $1,358 / $434 | $7,709 / $3,472 |
🔑 峰均比 ≥ 5 时,FaaS 开始占优;峰均比接近 1(稳态高负载)时,IaaS/预留便宜 1.5–3 倍。「QPS 低所以用 FaaS」这句话漏了后半句:低 QPS 且稀疏才省钱;低 QPS 但 7×24 常驻,FaaS 只是把固定成本换成了更贵的按量单价。
上面的表可以复算——把峰值并发按峰均比折成实例数,就是全部逻辑:
package main
import (
"fmt"
"math"
)
const (
gbSecond = 0.0000166667 // $/GB-秒
perReq = 0.20 / 1e6 // $/次
instMo = 31.0 // $/月,1 vCPU / 2 GiB
durSec = 0.2 // 每次执行 200ms
secMo = 730 * 3600.0
)
func faas(avgC, memGB float64) float64 { // 为平均值付费
busy := avgC * secMo
return busy*memGB*gbSecond + busy/durSec*perReq
}
func iaas(avgC, cpuPerRun, memGB, duty float64) float64 { // 为峰值付费
peak := avgC / duty
inst := math.Max(peak*cpuPerRun, peak*memGB/2)
return math.Max(1, math.Ceil(inst)) * instMo
}
func main() {
cpu, mem := 0.05, 0.25 // IO 型:每次执行 0.05 vCPU / 256MB
for _, duty := range []float64{0.1, 0.5, 0.9} {
for _, c := range []float64{10, 100, 1000} {
fmt.Printf("并发 %-5.0f 峰均比 %-4.1f FaaS $%-8.0f IaaS $%-8.0f\n",
c, 1/duty, faas(c, mem), iaas(c, cpu, mem, duty))
}
}
}
输出(节选,与上表 IO 型一致):
并发 10 峰均比 10.0 FaaS $136 IaaS $403
并发 100 峰均比 10.0 FaaS $1358 IaaS $3875
并发 1000 峰均比 10.0 FaaS $13578 IaaS $38750
并发 100 峰均比 2.0 FaaS $1358 IaaS $775
并发 1000 峰均比 1.1 FaaS $13578 IaaS $4309
第二个隐藏变量是打包率:256MB 的函数能在一个 2GiB 实例里并排跑 8 个,而 CPU 密集的函数只能跑 1 个。FaaS 按实际内存计费,IaaS 按整机规格计费——函数越轻、越 IO 密集,FaaS 越占便宜;越能吃满整机,IaaS 越便宜。
FaaS 的五个硬约束
| 约束 | 量级 / 口径 | 后果 | 绕法 |
|---|---|---|---|
| 冷启动 | 毫秒级(Go/Node 预热池)到秒级(JVM/Spring 初始化) | P99 抖动,首请求超时 | 预置并发、快照启动、把初始化挪到全局作用域、改用轻运行时 |
| 单次执行时长 | 公开口径上限 15 分钟(各平台不同,有的 5–10 分钟) | 长任务被强杀,重试放大副作用 | 拆成编排 + 多个函数,或改用 Job/容器 |
| 无状态 | 本地盘为临时目录,实例随时回收 | 会话、缓存、临时文件丢失 | 外置 Redis/对象存储;把状态显式化 |
| 并发与连接 | 账号级并发配额;长连接支持有限 | 突发被限流;WebSocket 不适用 | 申请提额、长连接走网关/容器 |
| 事件源绑定 | 触发器、IAM、VPC 配置与平台强绑定 | 迁移成本高 | 把业务逻辑与 handler 解耦,触发器薄层化 |
冷启动的根源不是「容器启动慢」(容器启动是 ms 级),而是运行时初始化:JVM 要加载类、Spring 要扫注解、Python 要 import 一堆包。所有「消灭冷启动」的手段,本质都是在复用已经初始化好的进程(预热池、快照恢复)。
可观测性与调试:能力随抽象递减
| 能力 | IaaS | PaaS | FaaS |
|---|---|---|---|
| SSH / 登录机器 | ✅ | 部分(跳板/调试容器) | ❌ |
| 抓包 | ✅ | 受限 | ❌ |
| CPU/内存 profile | ✅ 随时 | 部分平台支持 | 只在调用期间、按平台 |
| 本地复现 | 完全一致 | 基本一致 | 难(事件源、IAM、超时都要模拟) |
| 日志 | 自建采集 | 平台采集 | 平台采集(有大小/保留限制) |
| 排障粒度 | 进程/线程/系统调用 | 实例 | 单次调用 |
⚠️ FaaS 的排障盲区是冷启动与平台调度:同一次调用可能落在热实例(20ms)也可能冷启动(3s),日志里看不出区别。没有平台的冷启动指标,你会把「P99 抖动」误判成「下游慢」。
锁定:锁的不是代码,是周边
| 层次 | 迁移要改什么 | 锁定强度 |
|---|---|---|
| IaaS | 镜像可导出、IaC 换 provider | 低(主要是网络/IAM) |
| CaaS | K8s 清单基本可搬,存储类/网络插件要换 | 中 |
| PaaS | 构建方式、运行时版本、附加服务(DB/缓存)绑定 | 中高 |
| FaaS | 触发器、IAM、事件格式、部署工具、运行时限制 | 高 |
决策表
| 你的情况 | 选 | 理由 |
|---|---|---|
| 需要改内核参数、装 agent、特殊网络 | IaaS | 平台不给你这层权限 |
| 标准 Web 服务、流量平稳、团队小 | PaaS | 少运维,实例数可控 |
| 事件驱动、流量稀疏或脉冲、异步任务 | FaaS | 闲置成本为 0 |
| 长连接、WebSocket、有状态会话 | CaaS / IaaS | FaaS 的连接模型不匹配 |
| 单次任务 > 15 分钟 | Job / 容器 | 超出 FaaS 时长上限 |
| 稳态高负载、能吃满整机 | IaaS + 预留 | 单位算力最便宜 |
| 需要 GPU、特殊硬件 | IaaS | FaaS 基本不提供 |
| 已有 K8s 与平台团队 | CaaS + FaaS(Knative/OpenFaaS) | 复用调度与流水线 |
反模式
| 反模式 | 后果 |
|---|---|
| 用 QPS 单指标决定 FaaS/IaaS | 忽略峰均比与打包率,稳态负载上 FaaS 后账单翻倍 |
| 把 Spring Boot 直接搬上 FaaS | 每次冷启动都重跑初始化,P99 从 80ms 变 3s |
| 在函数里做长任务(视频转码、大批量导出) | 超时被强杀,重试导致重复扣费/重复写入 |
| 在函数实例内存会话或本地缓存 | 实例回收即丢,行为随机 |
| 把 FaaS 当「不用运维」 | 触发器、IAM、VPC、配额、冷启动都要人管 |
| 只算计算费,不算出网费与请求费 | 流量型业务的账单大头在出网,见 5.6 云成本结构 |
| 无预置并发就承诺 P99 SLA | 冷启动直接把尾延迟打穿 |
自检
Q1 一个批处理任务每天跑 2 小时、每次 40 分钟、内存 2 GiB,团队想用 FaaS。你会怎么算、怎么答?
▸ 答案:先算占空比:2/24 ≈ 8.3%,峰均比高,成本上 FaaS 占优。但 40 分钟单次执行会撞上 FaaS 的时长上限(公开口径常见 15 分钟,平台不同),所以不能把整批塞进一个调用,必须拆成「编排 + 多个 ≤15 分钟的函数」或直接用 Job/容器。结论:成本模型支持 FaaS,执行模型不支持——选型要同时过这两关。若拆分后每次调用有大量固定开销(拉数据、建连),拆分的总成本可能反超一台按小时计费的实例。
Q2 有人说「我们 QPS 只有 5,肯定用 FaaS 便宜」。这句话缺了哪三个变量?
▸ 答案:缺 ① 峰均比/占空比(5 QPS 是 7×24 还是每天 10 分钟);② 单次时长与内存(决定 GB-秒);③ 打包率(每次执行占多少 vCPU/内存,能否填满一台实例)。5 QPS 的常驻服务,FaaS 的按量单价往往高于一台小实例的月费;反之每天只跑 10 分钟的 5 QPS,FaaS 便宜一个量级。
Q3 团队把 Java 服务原样搬上 FaaS,压测发现 P50 25ms、P99 3.2s。为什么?列出两条治本手段。
▸ 答案:P50 是热实例,P99 是冷启动——JVM 启动 + 类加载 + Spring 上下文初始化都在调用路径上。治本:① 预置并发/预热池,让请求落在已初始化的实例;② 降低初始化成本:换轻量框架、把重初始化移到构建期(CDS/AppCDS、GraalVM native image)、减少启动期远程调用。加内存只能缩短一部分时间,不解决「每次新进程都要重新初始化」。
Q4 托管 K8s 应该算 IaaS 还是 PaaS?你的判断依据是什么?
▸ 答案:看责任线——控制面(API server/etcd/调度器)由云托管,但节点内核、kubelet、CNI、节点补丁、容量仍是你的,所以它是 CaaS,介于两者之间。判断依据始终是那三问:内核补丁谁打(你)、进程挂了谁拉起(k8s,但 k8s 本身你运维)、扩容谁决定(你配 HPA/Cluster Autoscaler,云只提供能力)。如果选了「托管节点池 + 自动伸缩」,责任线会向 PaaS 移动一截,但不会到 FaaS。
Q5 一个业务白天峰值是夜间的 12 倍,团队已经有一套 K8s。你会建议全量上 FaaS 吗?
▸ 答案:不建议「全量」。峰均比 12 的确适合 FaaS 的成本结构,但已有 K8s 意味着调度、发布、监控、网络都已沉没成本;更优的是按负载分层:脉冲型、无状态、事件驱动的部分(图片处理、webhook、定时任务)用 FaaS/Knative,长连接与核心交易留在 CaaS。判断标准是「这块负载的峰均比 × 是否无状态 × 是否值得多一套运维」,而不是统一技术栈的美感。
跨篇相关:容器与虚拟机的隔离边界决定 FaaS 多租户能不能信,见 6.1 容器与虚拟机的本质差异;FaaS 的伸缩由平台控制器完成,其模型见 7.1 声明式 API 与控制器模式;地域选择与可用区见 5.3 地域与可用区;弹性策略见 5.4 弹性伸缩与自动扩缩容;托管与自建的取舍见 5.5 托管服务与自建的取舍;成本结构见 5.6 云成本结构;厂商锁定与迁移见 5.7 云厂商锁定与迁移;部署形态的另一种切法见 33.3 Serverless / FaaS;单位经济与容量规划见 39.1 成本模型与单位经济、39.2 容量规划(待补)。