在计算实际的第一个月之前,耐用物品的定价似乎很简单。三个相互作用的组件,在您测量正确的内存占用量之前似乎很慷慨的免费层,以及在生产数量到达时远远超出大多数工程师预期的吞吐量上限。在投入生产之前了解其结构可以节省意外费用并在压力下进行建筑重新设计。
分层成本结构
工人付费计划是先决条件 - 每月 5 美元,没有它,DO 不可用。从那里:
索赔:每月第一百万免费后为 0.15 美元/百万。对 DO 存根的每次调用都算作一次请求。执行路由的工作人员使用正常的工作人员请求配额,与此分开。
以 GB 秒计算:每月 40 万免费后,每百万 GB 秒 12.50 美元。 GB-秒是工作单位:使用的内存(以 GB 为单位)乘以执行时间(以秒为单位)。每个 DO 实例的最小内存占用量为 128MB (0.125 GB)。 128MB 耗时 10 毫秒的请求会消耗 0.00125 GB 秒。
存储:1GB 免费后每月 0.20 美元/GB。累积 — 如果您有 1,000 个 DO,每个 DO 大小为 10KB,则相当于 10MB 存储空间,完全在可用范围内。如果每个实例保留较大的数据,存储成本就会开始出现。
警报:0.15 美元/百万次调用。与正常请求相同的表。
免费计算层的真实计算
这个数字是 40 万 GB 秒/月。每个实例的最小占用空间为 128MB,这相当于 320 万秒的执行时间 — 每月大约 889 小时的活动 DO,分布在所有 DO 之间。
重要的帐户是按工作量计算的,而不是按 DO 计算的。如果您的 DO 处理的请求时间从 10 毫秒到 128 MB,则每个请求消耗 0.00125 GB 秒。免费套餐涵盖了其中 3.2 亿个请求,远多于免费套餐的请求(100 万个)。对于具有轻量和快速 DO 的工作负载,免费计划的瓶颈是请求配额,而不是计算配额。
逆转这一情况的场景是在内存中维护大状态的 DO。如果 DO 将 2MB 文档加载到内存中以处理协作编辑,则其占用空间不是 0.125 GB — 加上隔离开销,它更接近 0.127 GB。对于加载大型 JSON、用于处理的图像缓冲区或大型本地缓存的 DO,实际 GB 秒随着内存中状态的大小而不是请求的执行时间而增长。
具体工作量的成本是多少? 100 万个 128MB 的 100 毫秒请求:100,000 GB 秒 = 1.25 美元计算费用(在免费计算层内,但在免费请求层之上:0.15 美元 × (1 − 1) = 如果是前一百万则免费,如果是第二百万则免费 0.15 美元)。总计:1.25 美元的计算 + 0.15 美元的额外请求 = 1.40 美元(加上计划中的 5 美元)。
比预期更早出现的吞吐量上限
串行执行保证了 DO 的一致性及其吞吐量上限。 DO 一次处理一个请求。每个实例的最大吞吐量与每个请求的平均时间成反比。
公式:最大吞吐量(req/s)= 1000ms / 每个请求的平均时间(ms)。
每个请求 5 毫秒处理:每个 DO 实例 200 个请求/秒。 10 毫秒处理:100 个请求/秒。 50ms 处理(包括作为对外部服务的调用的 I/O):20 req/s。
这个上限似乎很高,直到您拥有将所有请求路由到同一 DO ID 的流行功能为止。如果平均处理时间为 4 毫秒,每秒 500 条消息发送到同一 DO 的聊天室将每秒排队 300 多条消息。客户感受到的延迟与队列的大小成比例增加。
解决方案是分片。您无需直接从房间或资源派生 DO ID,而是根据标识符的哈希添加数字后缀:
0
每个分片都是一个独立的 DO 实例,具有自己的吞吐量上限。分片非常适合仅需要在分片内保证一致性的操作 - 如果您需要资源的所有分片之间的全局一致性,则解决方案会变得更加复杂。
令人惊讶的存储限制
2 每次调用最多返回 128 个条目。此限制没有明显记录,但每次您有一个存储了超过 128 个密钥的 DO 并调用 3 期望全套密钥时,它都会出现。
分页使用光标:
1
在开发过程中忽略这一点(DO 几乎没有数据)并在生产中发现具有 500 个密钥的错误,会默默地产生不正确的结果 - 应用程序收到前 128 个项目并表现得好像它们全部一样。
另一个限制:事务仅限于单个 DO 实例。不存在修改两个不同 DO 实例的原子事务。如果您的设计需要两个 DO 之间的原子性(例如,将信用从一个 DO 转移到另一个 DO),您需要在应用程序层实现两阶段提交协议,并在失败时进行补偿。对于大多数情况,这表明需要重新审视设计:要么状态应该位于同一个 DO 中,要么操作不需要实例之间严格的原子性。
投入生产后要监控什么
DO ID 的响应延迟是吞吐量瓶颈的最直接指标。如果特定 DO 的延迟时间不断增加,而其他 DO 的延迟时间变快,则这些特定 DO 正在排队请求 — 适合分片的候选者。
GB 秒消耗与请求数量的关系揭示了 DO 的内存占用量大于预期。如果 GB 秒/请求比率在不改变处理时间的情况下增长,则某些 DO 正在将更多状态加载到内存中。
按命名空间存储显示您在没有清理例程的情况下可能积累的数据增长。写入存储而不删除的 DO 会无限期地累积数据 — 每月 0.20 美元/GB 似乎很便宜,直到您拥有几 GB 的历史数据而没有人再访问为止。
每月 5 美元赚更多
每月 5 美元的基准涵盖付费计划。对于在免费套餐内使用的小型应用程序,这是总成本。对于增长的应用程序,三个维度(请求、计算、存储)的边际成本根据负载类型以不同的方式增长。
频繁的请求加载但处理较少:请求层在计算之前耗尽。解决方案:在到达DO之前检查是否有任何请求可以缓存在Worker层中。
处理负载繁重,请求很少:计算占主导地位。解决方案:测量实际内存占用和平均执行时间,并检查是否可以将部分计算移至执行路由的 Worker。
许多 DO 都拥有持久数据:存储占主导地位。解决方案:为不需要无限期持续的数据设置 TTL,并通过 Alarm API 实施清理例程。
生产中最普遍的限制是串行吞吐量和4。其余的你可以在文档中找到,然后你就会感到惊讶。您会在最初几天发现这两个具有实际流量。
另请阅读
- [生产中的 KV:有效的模式和一开始就具有误导性的模式5
- [Cloudflare Durable Objects:边缘的一致状态 - 真正改变的是什么6
- [生产中的 D1:性能、限制以及无法单独扩展的因素7
- [持久对象编程模型:与您曾经使用过的任何东西不同的地方8
- [持久对象和 WebSockets:无需专用服务器的多人游戏9
- [当耐用物品是错误答案时10
