Как запустить Durable Objects от Cloudflare на своих серверах с помощью celld
Райан Даль и команда Deno тихо выложили в опенсорс проект celld. Если вы когда-нибудь завидовали пользователям Cloudflare из-за их концепции Durable Objects, но не хотели связываться с вендорлоком, эта штука может вас заинтересовать.
celld — это демонический рантайм на Rust, который умеет запускать бандлы Cloudflare Workers и изолированные инстансы Durable Objects на вашем собственном железе. Без Etcd, без Raft и без громоздких сервисов координации.
В чём соль концепции
Традиционный бекенд обычно делится на stateless-микросервисы и одну большую реляционную базу данных. Когда нагрузка растёт, база неизбежно становится главным узким местом.
Cloudflare предложила другой подход. Каждый активный сущностный объект приложения (например, чат-комната, корзина покупателя или сессия документа) получает собственный V8-изолят и персональную базу данных SQLite. Объект оживает при поступлении запроса, держит состояние в памяти и локальном файле SQLite, а при простое просто засыпает.
Главная проблема заключалась в замкнутости экосистемы: запустить такую схему за пределами инфраструктуры Cloudflare до сих пор было практически невозможно.
Как устроен celld изнутри
Разработчики celld пошли по пути радикального упрощения. Архитектура ноды состоит из четырех компонентов:
- Встроенный V8 для выполнения JavaScript и TypeScript кода из бандлов Wrangler.
- Локальный SQLite для отдельного файла БД каждого объекта.
- S3-совместимое хранилище (AWS S3, MinIO, Cloudflare R2) в качестве единственного источника правды.
- Межсерверный транспорт с HMAC-подписью для обмена данными между нодами.
Самое интересное решение здесь — отказ от классических протоколов консенсуса. Нодам в кластере не нужно выбирать лидера или держать запущенный Consul.
Вместо этого сервера общаются с S3 через атомарную операцию Compare-And-Swap (CAS). Когда нода хочет забрать себе обслуживание объекта, она записывает файл владения в S3-бакет. Кто успел обновить запись через CAS, тот и обрабатывает трафик. Если нода падает, таймаут записи истекает, а соседний сервер подхватывает объект, скачивает его свежую SQLite-базу из бакета и продолжает работу.
Запуск и развёртывание
Для сборки проекта подходят обычные сборки Wrangler, но на сервере понадобится esbuild и сам бинарник celld.
Установка выполняется одной командой:
curl -fsSL https://celld.dev/install.sh | sh
Процесс работы разделен на два этапа. Сначала загружаем сборку воркера в бакет:
celld deploy . \
--bucket s3://my-cells-bucket
Затем запускаем демона на сервере:
celld \
--bucket s3://my-cells-bucket \
--listen 0.0.0.0:8080 \
--advertise 10.0.0.12:8080
Каждый узел в кластере читает манифест deploy/current.json из бакета. Если нужно поднять дополнительный сервер, вы запускаете ещё один процесс с тем же бакетом и указываете его сетевой адрес в --advertise.
По поводу безопасности: межсерверный трафик celld не шифрует TLS из коробки. Авторы рекомендуют убирать внутренние порты нод под защищенную оверлейную сеть вроде WireGuard или Tailscale. Все peer-запросы автоматически подписываются HMAC-ключом fleet/peer-auth.json, который первая нода автоматически создаёт в бакете.
Диагностика и управление нагрузкой
Для мониторинга кластера есть утилита diagnose. Она опрашивает соседей и показывает текущие метрики:
celld diagnose --bucket s3://my-cells-bucket
Команда выведет потребление CPU, RSS-памяти, количество активных WebSocket-подключений и число живых объектов на каждом узле.
Если сервер начинает перегружаться, в celld предусмотрен механизм сброса активных объектов (pressure shedding). Лимиты задаются через переменные окружения:
CELLD_MAX_RESIDENT_CELLS=1000 \
CELLD_RESIDENT_LOW_WATER=800 \
celld --bucket s3://my-cells-bucket --listen 0.0.0.0:8080 \
--advertise node-a.internal:8080
При превышении порога celld сохраняет неактивные объекты в S3, снимает с себя права владения и перестает принимать новые сущности, пока нагрузка не спадет до значения CELLD_RESIDENT_LOW_WATER. Объекты с частыми запросами или открытыми WebSocket-соединениями при этом не затрагиваются.
Необычный подход к контрибьютингу
Если вы зайдёте в репозиторий denoland/celld с намерением открыть Pull Request, кнопка окажется недоступна. Форки разрешены, а вот PR на GitHub отключены полностью.
Райан Даль объясняет это борьбой со спамом от ИИ-агентов: разбор гигантских автосгенерированных пулл-реквестов без контекста отнимает у мейнтейнеров слишком много времени. Желающим прислать патч предлагают делать git format-patch и отправлять файл письмом на личную почту ry@deno.com.
Кому стоит присмотреться к проекту
Проект находится в активной фазе разработки, спецификации протокола хранятся прямо в коде Rust-крайта crates/celld/protocol.rs. Тащить его в критичный продакшен пока рано, но поэкспериментировать точно стоит.
Инструмент пригодится в следующих случаях:
- Разработчикам мультиплеерных сервисов, чатов и кастомных CRM.
- Командам, планирующим уйти от привязки к Cloudflare без переписывания кода.
- Поклонникам архитектуры с отдельной базой данных на каждого клиенто-пользователя.
- Инженерам, изучающим распределённые системы без Raft и Etcd.
