← Cloudflare Durable Objects / durable-objects
Начало работы
Это руководство проведёт вас через следующие шаги:
- Написание класса JavaScript, определяющего Durable Object.
- Используйте Durable Objects SQL API для запросов к приватной встроенной базе данных SQLite объекта Durable Object.
- Создание экземпляра Durable Object и обмен данными с ним из другого Worker.
- Развёртывание Durable Object и Worker, который взаимодействует с Durable Object.
Чтобы узнать больше о Durable Objects, см. Что такое Durable Objects?.
быстрый старт
Если вы хотите пропустить шаги и быстро начать работу, нажмите кнопку ниже.
Это создаёт репозиторий в вашем аккаунте GitHub и разворачивает приложение в Cloudflare Workers. Выберите этот вариант, если вы уже знакомы с Cloudflare Workers и хотите пропустить пошаговые инструкции.
Если вы только начинаете работать с Cloudflare Workers, можете пройти все шаги вручную.
Предварительные требования
- Зарегистрируйтесь для получения Аккаунт Cloudflare ↗.
- Установка
Node.js↗.
менеджер версий Node.js
Используйте менеджер версий Node, например Volta ↗ или nvm ↗ чтобы избежать проблем с правами доступа и переключать версии Node.js. Wrangler, о котором пойдёт речь далее в этом руководстве, требует версию Node 16.17.0 или более поздней версии.
1. Создайте проект Worker
Вы будете обращаться к своему Durable Object из Worker. Приложение Worker служит интерфейсом для взаимодействия с вашим Durable Object.
Чтобы создать проект Worker, выполните:
npm create cloudflare@latest -- durable-object-starterВыполнение create cloudflare@latest установит Wrangler, интерфейс командной строки Workers. Вы будете использовать Wrangler для тестирования и развёртывания своего проекта.
Для настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Hello World example. - Для Какой шаблон вы хотите использовать?, выберите
Worker + Durable Objects. - Для Какой язык вы хотите использовать?, выберите
TypeScript. - Для Хотите использовать git для контроля версий?, выберите
Yes. - Для Хотите развернуть приложение?, выберите
No(мы внесём некоторые изменения перед развёртыванием).
Это создаст новый каталог, в котором будет либо src/index.js или src/index.ts файл для написания кода и wrangler.jsonc файл конфигурации.
Перейдите в новый каталог:
cd durable-object-starter2. Напишите класс Durable Object с использованием SQL API
Прежде чем создавать Durable Object и обращаться к нему, его поведение нужно определить обычным экспортируемым классом JavaScript.
Ваш MyDurableObject класс будет иметь конструктор с двумя параметрами. Первый параметр, ctx, передаваемый в конструктор класса, содержит состояние, специфичное для Durable Object, включая методы доступа к хранилищу. Второй параметр, env, содержит все bindings, которые вы связали с Worker при его загрузке.
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
// Required, as we're extending the base class.
super(ctx, env);
}
}export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
// Required, as we're extending the base class.
super(ctx, env)
}
}from workers import DurableObject
class MyDurableObject(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)Workers взаимодействуют с Durable Object с помощью удалённый вызов процедур. Публичные методы класса Durable Object доступны как Методы RPC чтобы его можно было вызвать из другого Worker.
Теперь ваш файл должен выглядеть так:
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
// Required, as we're extending the base class.
super(ctx, env);
}
async sayHello() {
let result = this.ctx.storage.sql
.exec("SELECT 'Hello, World!' as greeting")
.one();
return result.greeting;
}
}export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
// Required, as we're extending the base class.
super(ctx, env)
}
async sayHello(): Promise<string> {
let result = this.ctx.storage.sql
.exec("SELECT 'Hello, World!' as greeting")
.one();
return result.greeting;
}
}from workers import DurableObject
class MyDurableObject(DurableObject):
async def say_hello(self):
result = self.ctx.storage.sql.exec(
"SELECT 'Hello, World!' as greeting"
).one()
return result.greetingВ приведённом выше коде вы:
- Определён RPC-метод,
sayHello(), который может быть вызван Worker для взаимодействия с Durable Object. - Реализован доступ к подключённому хранилищу Durable Object, приватной базе данных SQLite, доступной только самому объекту, с помощью SQL API методы (
sql.exec()) доступно наctx.storage. - Возвращает объект, представляющий результат запроса в виде одной строки, с помощью
one(), который проверяет, что результат запроса содержит ровно одну строку. - Возврат
greetingстолбец из объекта результата строки.
3. Создание экземпляра Durable Object и обмен данными с ним
Worker используется для Доступ к Durable Objects.
Чтобы взаимодействовать с Durable Object, обработчик fetch в Worker должен выглядеть примерно так:
export default {
async fetch(request, env, ctx) {
const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);
const greeting = await stub.sayHello();
return new Response(greeting);
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);
const greeting = await stub.sayHello();
return new Response(greeting);
},
} satisfies ExportedHandler<Env>;from workers import handler, Response, WorkerEntrypoint
from urllib.parse import urlparse
class Default(WorkerEntrypoint):
async def fetch(request):
url = urlparse(request.url)
stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
greeting = await stub.say_hello()
return Response(greeting)В приведённом выше коде вы:
- Экспортировали основные обработчики событий вашего Worker, такие как
fetch()-обработчик для получения HTTP-запросов. - Передано
envвfetch()-обработчик. Привязки (bindings) передаются как свойство объекта окружения, который передаётся вторым параметром при вызове обработчика события или конструктора класса. - Создана заглушка (stub) для экземпляра Durable Object на основе переданного имени. Заглушка представляет собой клиентский объект, который используется для отправки сообщений Durable Object.
- Обратился к Durable Object, вызвав RPC метод,
sayHello(), на Durable Object, который возвращаетHello, World!строку приветствия. - Возврат HTTP-ответа клиенту путём создания HTTP Response с
return new Response().
См. Доступ к Durable Object из Worker чтобы узнать больше о взаимодействии с Durable Object.
4. Настройка привязок Durable Object
Bindings позволяют вашим Workers взаимодействовать с ресурсами платформы Cloudflare для разработчиков. Привязки Durable Object в конфигурационном файле вашего проекта Worker конфигурационный файл Wrangler будет включать имя привязки (в этом руководстве используется MY_DURABLE_OBJECT) и имя класса (MyDurableObject).
{
"durable_objects": {
"bindings": [
{
"name": "MY_DURABLE_OBJECT",
"class_name": "MyDurableObject"
}
]
}
}[[durable_objects.bindings]]
name = "MY_DURABLE_OBJECT"
class_name = "MyDurableObject" bindings раздел содержит следующие поля:
name- Обязательно. Имя привязки, используемое в вашем Worker.class_name- Обязательно. Имя класса, к которому требуется выполнить привязку.script_name- Необязательно. По умолчанию используется текущий окружения код Worker.
5. Настройка класса Durable Object с бэкендом хранения SQLite
Каждый класс Durable Object, экспортируемый вашим Worker, объявляется в exports поле файла конфигурации Wrangler. Cloudflare использует это объявление, чтобы выделить пространство имён для класса при первом развёртывании и управлять его жизненным циклом при последующих развёртываниях (переименование, удаление, перенос).
Минимальный exports блок для регистрации нового класса Durable Object с хранилищем SQLite выглядит так:
{
"exports": {
"MyDurableObject": {
"type": "durable-object",
"storage": "sqlite"
}
}
}[exports.MyDurableObject]
type = "durable-object"
storage = "sqlite"См. Экспорт классов Durable Object чтобы узнать больше об объявлении и управлении классами Durable Object. Если у вас уже есть Worker на устаревшем migrations массив, см. Миграции классов Durable Object (устаревший способ).
6. Локальная разработка Durable Object Worker
Чтобы протестировать свой Durable Object локально, выполните wrangler dev:
npx wrangler devВ консоли вы должны увидетьHello world строку, возвращённую Durable Object.
7. Развёртывание Durable Object Worker
Чтобы развернуть Worker с Durable Object:
npx wrangler deployПосле развёртывания вы сможете увидеть только что созданный Durable Object Worker на панели управления Cloudflare.
Перейдите в Workers & Pages ↗Предварительный просмотр Worker с Durable Object доступен по адресу <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev.
Итоги и финальный код
Итоговый код должен выглядеть так:
import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject {
constructor(ctx, env) {
// Required, as we are extending the base class.
super(ctx, env);
}
async sayHello() {
let result = this.ctx.storage.sql
.exec("SELECT 'Hello, World!' as greeting")
.one();
return result.greeting;
}
}
export default {
async fetch(request, env, ctx) {
const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);
const greeting = await stub.sayHello();
return new Response(greeting);
},
};import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
// Required, as we are extending the base class.
super(ctx, env)
}
async sayHello():Promise<string> {
let result = this.ctx.storage.sql
.exec("SELECT 'Hello, World!' as greeting")
.one();
return result.greeting;
}
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);
const greeting = await stub.sayHello();
return new Response(greeting);
},
} satisfies ExportedHandler<Env>;from workers import DurableObject, handler, Response
from urllib.parse import urlparse
class MyDurableObject(DurableObject):
async def say_hello(self):
result = self.ctx.storage.sql.exec(
"SELECT 'Hello, World!' as greeting"
).one()
return result.greeting
class Default(WorkerEntrypoint):
async def fetch(self, request):
url = urlparse(request.url)
stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
greeting = await stub.say_hello()
return Response(greeting)После завершения этого руководства вы:
- Durable Object успешно создан
- Обратился к Durable Object, вызвав Метод RPC
- Durable Object развёрнут глобально
Дополнительные материалы
- Создание заглушек Durable Object
- Доступ к хранилищу Durable Objects
- Miniflare ↗ - Полезные инструменты для мокирования и тестирования Durable Objects.