Deno 团队开源的 Celld,试图把 Cloudflare Workers 与 Durable Objects 的编程模型带到自托管环境中。它不是一个需要复杂控制平面的云平台,而是一个可以运行在自己机器上的守护进程:对象按名称寻址,各自使用独立的 SQLite 数据库,并通过 S3 兼容存储在节点之间协调和复制。
这套设计的吸引力在于简单。开发者可以继续围绕“一个有状态对象处理一类请求”来组织代码,同时把数据和运行环境掌握在自己的基础设施里。代价也同样明确:系统可靠性、存储可用性、备份策略和多节点运维,都需要由使用者自己负责。
把状态拆成一个个对象
Celld 的核心模型是 Durable Object。每个对象通过名称定位,例如 room:alpha、user:42 或 counter:global。同一个名称对应同一个逻辑状态,而不是由应用自己在一个大数据库里维护大量租户键或分片键。
摘要中提到,每个对象都是一个独立的 SQLite 数据库。这种边界带来几个实际效果:
- 对象之间的状态天然隔离,数据模型可以围绕单个对象设计。
- 本地开发更直观,可以直接检查某个对象的 SQLite 数据库。
- 备份和恢复可以按对象进行,而不必总是处理一整套业务数据库。
- 对象数量、文件数量和存储管理会成为新的运维问题,不能把“独立数据库”理解成没有成本的无限扩展。
按名称寻址也会影响 API 设计。请求路由应当先确定对象名称,再把请求交给该对象处理。名称需要稳定、可预测,并且最好经过规范化,避免同一个业务实体因为大小写、编码或路径格式不同而产生多个对象。
用 S3 兼容存储协调节点
Celld 的另一个关键选择是:节点之间只通过用户自己的 S3 兼容存储库协调。摘要明确指出,它没有控制平面,也没有共识协议。
这意味着对象数据和节点协作信息都依赖外部对象存储的行为。部署时需要重点确认以下条件:
- 所有 Celld 节点都能访问同一个 S3 兼容端点。
- 节点使用独立、权限足够但范围受限的访问凭据。
- 存储桶具备可靠的持久化能力,并有生命周期、版本控制或备份策略。
- 网络分区、S3 请求超时和临时不可用时,应用能够接受请求失败或延迟。
没有共识协议并不等于没有一致性问题,而是把协调机制收敛到对象存储上。运营团队需要理解这种取舍:系统组件更少,部署路径更短;但最终的可用性和故障恢复边界,取决于 S3 兼容存储及其网络路径。
一个可改造的部署示例
下面是一个最小的环境变量示例。它表达的是部署思路,具体变量名和启动参数应以 Celld 实际版本的文档为准。把示例中的端点、桶名和凭据替换成自己的 S3 兼容存储配置后,再启动 Celld 守护进程。
#!/usr/bin/env bash
set -euo pipefail
export CELLD_S3_ENDPOINT="https://s3.example.internal"
export CELLD_S3_BUCKET="celld-production"
export CELLD_S3_REGION="us-east-1"
export CELLD_S3_ACCESS_KEY_ID="replace-me"
export CELLD_S3_SECRET_ACCESS_KEY="replace-me"
# 启动命令仅作为部署示意,请按实际发布版本调整。
exec celld
可以先用一个本地 S3 兼容服务验证网络和权限,再把端点切换到生产存储。下面是一个 Docker Compose 风格的伪配置,适合用来表达节点共享同一对象存储的结构;镜像名、端口和 Celld 参数同样需要根据实际版本调整。
services:
celld-1:
image: your-celld-image:latest
environment:
CELLD_S3_ENDPOINT: http://object-store:9000
CELLD_S3_BUCKET: celld-dev
CELLD_S3_REGION: us-east-1
CELLD_S3_ACCESS_KEY_ID: dev-access-key
CELLD_S3_SECRET_ACCESS_KEY: dev-secret-key
depends_on:
- object-store
celld-2:
image: your-celld-image:latest
environment:
CELLD_S3_ENDPOINT: http://object-store:9000
CELLD_S3_BUCKET: celld-dev
CELLD_S3_REGION: us-east-1
CELLD_S3_ACCESS_KEY_ID: dev-access-key
CELLD_S3_SECRET_ACCESS_KEY: dev-secret-key
depends_on:
- object-store
object-store:
image: minio/minio:latest
command: server /data
environment:
MINIO_ROOT_USER: dev-access-key
MINIO_ROOT_PASSWORD: dev-secret-key
这个例子只展示配置关系:两个 Celld 节点指向同一个对象存储。生产环境还需要补齐持久化卷、密钥管理、健康检查、TLS、备份和监控。不要直接把开发配置中的明文凭据用于生产。
适合什么场景
Celld 更适合状态边界清晰、按名称访问、希望自主管理基础设施的应用。例如实时房间、协作会话、用户级状态、轻量工作流或需要把业务状态绑定到某个逻辑实体的服务,都可以评估这种模型。
它不一定适合所有数据库工作负载。需要跨对象复杂事务、集中式分析查询、强一致多节点写入,或者依赖成熟数据库集群运维能力的系统,仍然应当优先考虑传统数据库或专门的分布式存储。独立 SQLite 数据库能简化对象隔离,却不能自动提供跨对象事务和全球一致性。
采用前可以做一轮小规模验证:
- 创建、读取和恢复同一个名称对象,确认寻址语义符合预期。
- 模拟 S3 延迟、短暂不可用和节点重启,记录请求行为。
- 测量对象数量增加后,SQLite 文件、元数据和备份任务的增长速度。
- 明确对象存储的权限、保留策略、版本控制和灾备责任。
- 为对象命名、幂等写入、超时和重试制定应用层规则。
结语
Celld 的价值不只在于“把某个云服务自托管化”,更在于提供了一种清晰的状态组织方式:对象按名称存在,各自拥有本地数据库,节点通过用户掌控的对象存储协作。它用较少的基础设施换取更直接的部署模型,同时把一致性、可用性和恢复能力的责任交回运营团队。
如果你的应用天然由许多独立、有状态的实体组成,Celld 值得在测试环境中验证。真正进入生产前,应把 S3 兼容存储当作关键基础设施来设计,并把故障注入、备份恢复和容量增长纳入验收,而不是只验证守护进程能否启动。