如何使用 celld 在自己的服务器上运行 Cloudflare Durable Objects
Ryan Dahl 和 Deno 团队悄然开源了 celld 项目。如果你一直羡慕 Cloudflare 用户的 Durable Objects 概念,但又不想受制于供应商锁定,这可能会引起你的兴趣。
celld 是一个 Rust 守护进程运行时,可以在你的自有硬件上运行 Cloudflare Workers bundles 和隔离的 Durable Objects 实例。无需 Etcd、无需 Raft、无需重量级协调服务。
概念核心
传统后端通常分为无状态微服务和单一大型关系数据库。随着负载增加,数据库不可避免地成为主要瓶颈。
Cloudflare 提出了不同的方案。每个活跃的应用实体(例如聊天室、购物车或文档会话)都有自己的 V8 隔离实例和独立的 SQLite 数据库。对象在请求到达时唤醒,在内存和本地 SQLite 文件中保持状态,空闲时则进入休眠状态。
主要问题在于生态系统的封闭性:在此之前,在 Cloudflare 基础设施之外运行这样的设置几乎是不可能的。
celld 的内部工作原理
celld 开发人员追求极致的简化。节点架构由四个组件构成:
- 嵌入式 V8 引擎,用于执行 Wrangler bundles 中的 JavaScript 和 TypeScript 代码。
- 本地 SQLite,每个对象都有独立的数据库文件。
- S3 兼容存储(AWS S3、MinIO、Cloudflare R2)作为唯一的真相源。
- 节点间数据交换使用 HMAC 签名的服务器间传输。
这里最有趣的解决方案是放弃了经典的共识协议。集群节点无需选举领导者或运行 Consul。
相反,服务器通过原子比较-交换(CAS)操作与 S3 通信。当节点想要获取对象的所有权时,它会向 S3 存储桶写入一个所有权文件。第一个通过 CAS 成功更新记录的节点处理流量。如果节点崩溃,写入超时过期,邻近服务器会接管对象,从存储桶下载最新的 SQLite 数据库并继续运行。
启动与部署
标准的 Wrangler 构建可用于构建项目,但你需要一台装有 5 的服务器和二进制文件本身 6。
安装只需一条命令:
0工作流程分为两个步骤。首先,将 worker 构建上传到存储桶:
1然后在服务器上启动守护进程:
2集群中的每个节点从存储桶读取清单 7。如果需要启动额外的服务器,你可以使用相同的存储桶启动另一个进程,并在 8 中指定其网络地址。
关于安全性:celld 的服务器间流量默认不加密 TLS。作者建议将内部节点端口放在 WireGuard 或 Tailscale 等安全覆盖网络后面。所有对等请求都使用 HMAC 密钥 9 自动签名,该密钥由第一个节点在存储桶中自动创建。
诊断与负载管理
对于集群监控,有 10 工具可用。它会轮询邻居并显示当前指标:
3该命令会输出 CPU 消耗、RSS 内存、活跃 WebSocket 连接数以及每个节点上存活对象的数量。
如果服务器开始过载,celld 有一个针对活跃对象的压力卸载机制。限制通过环境变量设置:
4当超过阈值时,celld 会将不活跃的对象保存到 S3、释放所有权,并停止接受新实体,直到负载降至 11 的值。请求频繁或具有开放 WebSocket 连接的对象不受影响。
一种不寻常的贡献方式
如果你访问 12 仓库打算提交 Pull Request,你会发现按钮是禁用的。允许 fork,但 GitHub 上的 PR 完全被禁用。
Ryan Dahl 将此解释为对抗 AI 代理垃圾信息的措施:审查没有上下文的巨型自动生成 pull request 会占用维护者太多时间。想要发送补丁的人需要生成 13 并将文件通过电子邮件发送到个人地址 14。
谁应该关注这个项目
该项目正在积极开发中,协议规范直接存储在 Rust crate 代码 15 中。现在将其用于关键生产环境还为时过早,但尝试一下绝对值得。
该工具在以下场景中会很有用:
- 多人服务、聊天和自定义 CRM 的开发者。
- 计划在不重写代码的情况下摆脱 Cloudflare 锁定的团队。
- 喜欢每个客户端-用户独立数据库架构的人。
- 学习分布式系统但不想要 Raft 和 Etcd 的工程师。
相关项目