Modal 容器容量 · 2026 年 8 月 14 日定价

预热池成本账

为应对突发流量、随时备好 150 个任务容器,有两种做法。一种全天 24 小时为「随时就绪」付费,另一种只在突发真正会来的那几个小时付费。

每天 1,000 个任务 图片 500 · 视频 500 峰值目标 同时 150 仅含编排层 —— 生成费用另计

两种方案

方案 A

全天常备 150

$2,613每月

150 个容器全天每一秒都保持预热。任何时刻来的突发流量,等待时间都是 0 秒。代码里设一次,之后不用再管。

凌晨 03:00 预热数
150
下午 14:00 预热数
150
每月付费容器·小时
108,000
每个任务成本
$0.087
每年
$31,356
方案 B

按时段预热

$1,418每月

08:00 到 18:00 预热 150 个,夜间降到 20 个保底。在时段内的响应与方案 A 完全一样。时段外超过 20 个的突发要等一次冷启动。

凌晨 03:00 预热数
20
下午 14:00 预热数
150
每月付费容器·小时
53,400
每个任务成本
$0.047
每年
$17,016
每年省 $14,340

钱花在哪里 —— 看时钟

两种方案的能力完全相同,区别只在于容量什么时候是预热的。下面每一根柱子代表一天中的一个小时,柱高代表预热容器数。

方案 A · 全天常备 每月 108,000 付费容器·小时
方案 B · 08:00–18:00 预热 每月 53,400 付费容器·小时
0246 8101214 16182022

方案 B 把付费容器·小时砍掉 51% —— 每月 54,600 小时是买了却从没用上的。

成本拆解

成本项 容器·小时 / 月 方案 A 方案 B
150 预热 —— 全天(24 小时)108,000$2,363
150 预热 —— 时段内(10 小时)45,000$985
20 保底 —— 时段外(14 小时)8,400$184
任务本身的算力(已在预热池内)$0$0
Team 套餐 —— 超过 100 容器必须升级$250$250
每月合计 $2,613 $1,418

任务是跑你已经付过钱的预热容器上,所以按任务算的算力费用不额外增加。这一点容易被忽略:干活是免费的,「随时就绪」才是账单。

时段长短如何影响账单

150 个容器每保持预热 1 小时,成本 $98。降到 20 保底的每小时成本 $13。选定时段,就能读出价格。

24 小时(= A) $2,613
16 小时 $1,930
12 小时 $1,589
10 小时(= B) $1,418
8 小时 $1,248
4 小时 $906

曲线越往下越平,因为有两笔钱永远不变:夜间 20 个容器的保底,和 $250 的套餐费。时段压到 8 小时以下,省得不多,却明显丢覆盖范围。

两种方案各能覆盖什么

场景方案 A方案 B
14:00,150 个任务同时到达等 0 秒等 0 秒
03:00,150 个任务同时到达等 0 秒130 个等约 25 秒
03:00,30 个任务同时到达等 0 秒10 个等约 25 秒
03:00,20 个任务同时到达等 0 秒等 0 秒
任何时刻超过 150 的任务排队排队
需要运维的活动部件2 个定时任务

方案 B 在时段内并不更弱,只在时段外更弱。所以整个选择归结为客户的一个问题:突发流量会在凌晨 3 点出现吗?

方案 B —— 怎么实现

用两个定时函数切换预热池大小。Modal 原生支持,不需要外部调度器。

@app.cls(min_containers=20, max_containers=150, scaledown_window=600, ...)
class Processor: ...

@app.function(schedule=modal.Cron("50 7 * * *", timezone="Asia/Ulaanbaatar"))
def warm_up():
    Processor().update_autoscaler(min_containers=150)   # 时段开始前 10 分钟

@app.function(schedule=modal.Cron("0 18 * * *", timezone="Asia/Ulaanbaatar"))
def cool_down():
    Processor().update_autoscaler(min_containers=20)

风险 1 —— 一次部署会悄悄取消它

update_autoscaler 设的值会在下一次部署时回退到装饰器里的值。如果 10:00 部署,预热池会在时段中途从 150 掉回 20,而且任何地方都不会报错。时段内做的任何部署,都必须重新跑一次 warm_up

风险 2 —— 150 个容器不会瞬间出现

定时任务必须在时段开始之前触发,而不是在开始那一刻。这就是为什么 08:00 的时段要让 warm_up 在 07:50 跑 —— 留 10 分钟提前量。

免费的改进 —— scaledown_window=600

突发期间拉起来的容器,在突发结束后还会再保持预热 10 分钟。这 10 分钟内的第二波突发是瞬时响应的。两种方案都受益,且不增加任何费用。

敏感性分析 —— 每容器内存

目前这个 class 上既没设 cpu= 也没设 memory=,所以 Modal 按容器实际用量计费。2 GiB 那一行是本报告采用的估算值,另外两行给出上下界。

每容器内存$/容器/月方案 A方案 B
1 GiB$10.00$1,750$992
2 GiB —— 采用的估算值$15.75$2,613$1,418
4 GiB$27.26$4,339$2,272

最坏情况下账单翻倍。显式设一个 memory= 就能把这个风险封住,预测也才算落地 —— 算不出上限的账单,不能算报价。

建议

先上方案 B,10 小时时段:每月 $1,418。在有流量的那些小时里,它和方案 A 完全一样;在没有流量的小时里,它每年省下 $14,340。

只有当客户确认突发流量可能落在时段之外时,才升到方案 A。差价是每月 $1,195 —— 这就是「凌晨 3 点也随时就绪」的老实价格。

在两个数字落定之前还有两件事:显式设 memory=,让账单有上限;重新测一次冷启动。代码里那个 25 秒是加 memory snapshot 之前测的,如果实际恢复只要 3–5 秒,那么用小得多的预热池就能扛住同样的突发,两个数字都会往下走。