El problema fundamental que Celld aborda es la gestión de estado distribuido y la ejecución de código serverless con alta disponibilidad y escalabilidad horizontal, sin la complejidad inherente a los sistemas de consenso distribuido tradicionales. Al encapsular cada Durable Object como su propia base de datos SQLite y replicar su estado a un almacenamiento de objetos S3-compatible, Celld resuelve el desafío de la consistencia y durabilidad del estado en un entorno distribuido.
La arquitectura de Celld se inspira en el modelo de Durable Objects de Cloudflare, que proporciona una primitiva de concurrencia distribuida basada en la idea de un objeto con estado que solo puede ser modificado por una única instancia lógica a la vez. Esto simplifica la programación distribuida al eliminar muchas de las complejidades asociadas con la consistencia de datos y la coordinación entre nodos. La novedad de Celld radica en cómo logra esta durabilidad y coordinación sin un plano de control centralizado, utilizando el almacenamiento de objetos como la única fuente de verdad y el mecanismo de coordinación.
Este enfoque es particularmente relevante en la era de la computación en la nube y el edge computing, donde la necesidad de desplegar y escalar aplicaciones con estado de manera eficiente y resiliente es crítica. Al evitar la sobrecarga de un sistema de consenso como Raft o Paxos, Celld busca ofrecer una solución más ligera y fácil de operar para cargas de trabajo que se benefician de un modelo de objetos durables.
Arquitectura del Sistema
La arquitectura de Celld se compone de nodos individuales que ejecutan el daemon celld. Cada nodo incrusta el motor V8 para ejecutar bundles de Cloudflare Workers. La flota de nodos comparte un único bucket S3-compatible, que actúa como el almacenamiento duradero para los despliegues de Workers, el estado de los Durable Objects (referidos como 'cells') y los registros de propiedad.
Cada Durable Object ('cell') es una instancia de SQLite, lo que significa que su estado se almacena localmente en una base de datos relacional. Celld replica continuamente esta base de datos SQLite al bucket S3. Cuando un objeto se mueve entre nodos o se activa después de hibernar, su nuevo propietario restaura la base de datos desde el bucket S3 y reanuda la ejecución. El bucket S3 es la fuente de verdad duradera, lo que hace que los nodos sean completamente reemplazables y sin estado efímero crítico.
La coordinación entre nodos para la propiedad de los objetos se realiza a través de operaciones de 'compare-and-swap' en el almacenamiento de objetos. Esto permite que exactamente un nodo sea el propietario de una 'cell' en un momento dado, sin necesidad de un protocolo de membresía, un detector de fallos o un servicio de consenso distribuido explícito. Los nodos descubren a otros propietarios y pares a través de 'leases' almacenados en el bucket. La comunicación entre pares utiliza HTTP, con autenticación HMAC, límites de reloj y protección contra repeticiones, y se espera que se realice en una red privada o superpuesta cifrada.
Flujo de Despliegue de un Worker
- 1 Desarrollador Ejecuta `celld deploy . --bucket s3://my-cells-bucket`
- 2 celld deploy Invoca `esbuild` para compilar el Worker y assets
- 3 celld deploy Escribe objetos de despliegue en el bucket S3 (ej. `deploy/current.json`)
- 4 Nodos celld Cargan el último despliegue exitoso desde `deploy/current.json`
Flujo de Vida de un Durable Object (Cell)
- 1 Solicitud Entrante Un nodo `celld` recibe una solicitud para un Durable Object
- 2 Adquisición de Propiedad El nodo intenta adquirir la propiedad del objeto vía 'compare-and-swap' en S3
- 3 Restauración de Estado Si es nuevo propietario, restaura la base de datos SQLite del objeto desde S3
- 4 Ejecución V8 El nodo ejecuta el código del Worker en V8, interactuando con SQLite
- 5 Replicación Continua El estado de SQLite se replica continuamente al bucket S3
- 6 Hibernación/Movimiento Si el objeto está inactivo o bajo presión, se replica y se libera la propieda...
| Capa | Tecnología | Justificación |
|---|---|---|
| compute | V8 | Motor de ejecución JavaScript para Cloudflare Workers y Durable Objects. |
| storage | SQLite | Base de datos local para la persistencia del estado de cada Durable Object ('cell'). |
| storage | S3-compatible Object Storage | Almacenamiento duradero para el estado replicado de los Durable Objects, despliegues de Workers y registros de propiedad. Actúa como la fuente de verdad y el mecanismo de coordinación. --bucket s3://my-cells-bucket, --endpoint https://ACCOUNT.r2.cloudflarestorage.com |
| networking | HTTP | Protocolo de comunicación entre nodos `celld` para la coordinación de pares. Requiere una red privada o cifrada. HMAC-authenticated, clock-bounded, replay-protected |
| orchestration | Object-storage compare-and-swap | Mecanismo para asegurar la propiedad exclusiva de un Durable Object por un único nodo, sin un protocolo de consenso explícito. vs Raft, Paxos |
| data-processing | esbuild | Bundler de JavaScript utilizado por `celld deploy` para compilar y empaquetar el código de los Workers. Necesita estar en PATH |
Trade-offs
Ganancias
- ▲ Simplicidad operativa
- ▲ Escalabilidad horizontal por objeto
- ▲ Resiliencia de nodos (son reemplazables)
- ▲ Reducción de blast radius (aislamiento por objeto)
Costes
- ▲ Dependencia de la latencia y disponibilidad del almacenamiento de objetos
- △ Costo de operaciones de almacenamiento de objetos
- △ Complejidad de la red para la comunicación entre pares (requiere red privada/cifrada)
curl -fsSL https://celld.dev/install.sh | sh
# ...
curl -fsSL https://celld.dev/uninstall.sh | shdocker run --rm --network host \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_SESSION_TOKEN \
-e CELLD_WATCH=/var/lib/celld/state \
-v celld-state:/var/lib/celld \
ghcr.io/denoland/celld \
--bucket s3://my-cells-bucket \
--endpoint https://ACCOUNT.r2.cloudflarestorage.com \
--region auto \
--listen 0.0.0.0:8080 \
--advertise node-a.internal:8080Fundamentos Teóricos
El diseño de Celld, al delegar la durabilidad y la coordinación a un servicio de almacenamiento de objetos, se alinea con el principio de 'shared-nothing architecture' en el sentido de que los nodos de cómputo no comparten directamente el estado mutable. Sin embargo, el almacenamiento de objetos actúa como un recurso compartido para la persistencia y la coordinación. Este enfoque puede verse como una aplicación práctica de los principios de los sistemas de archivos distribuidos y las bases de datos distribuidas que buscan la consistencia eventual o la consistencia fuerte a través de un mecanismo de bloqueo centralizado (en este caso, el 'compare-and-swap' del almacenamiento de objetos).
La idea de encapsular el estado y la lógica de negocio en 'objetos durables' que se ejecutan en una única instancia lógica a la vez, se remonta a conceptos de sistemas distribuidos como los 'actors' o los 'monitores distribuidos', que buscan simplificar la programación concurrente y distribuida al garantizar la exclusión mutua a nivel de objeto. Aunque Celld no implementa un sistema de actores completo, la restricción de que solo un nodo posee y modifica un objeto en un momento dado es un patrón bien establecido para gestionar el estado concurrente. La dependencia de un almacenamiento de objetos para la durabilidad y la coordinación es una evolución moderna de estos principios, aprovechando la alta disponibilidad y durabilidad que ofrecen los servicios de almacenamiento en la nube.