← Cloudflare Durable Objects / durable-objects / concepts
Жизненный цикл Durable Object
В этом разделе описан жизненный цикл Durable Object.
Чтобы использовать Durable Object, нужно создать Durable Object Stub. Простое создание Durable Object Stub не отправляет запрос к Durable Object, поэтому Durable Object ещё не создан. Запрос отправляется к Durable Object, и его жизненный цикл начинается только после вызова метода на Durable Object Stub.
const stub = env.MY_DURABLE_OBJECT.getByName("foo");
// Now the request is sent to the remote Durable Object.
const rpcResponse = await stub.sayHello();Переходы состояний жизненного цикла Durable Object
В любой момент времени Durable Object может находиться в одном из следующих состояний:
| Состояние | Описание |
|---|---|
| Активный, в памяти | Durable Object работает в памяти и обрабатывает входящие запросы. |
| Простаивает, в памяти, не поддерживает гибернацию | Durable Object ожидает следующий входящий запрос или событие, но не соответствует критериям гибернации. |
| Простаивает, в памяти, поддерживает гибернацию | Durable Object ожидает следующий входящий запрос или событие и соответствует критериям гибернации. Решение о том, когда переводить Durable Object в спящий режим, принимает среда выполнения. В настоящее время это происходит после 10 секунд бездействия в этом состоянии. |
| Гибернировано | Durable Object выгружается из памяти. Гибернированные соединения WebSocket остаются подключёнными. |
| Неактивен | Durable Object полностью выгружается из процесса-хоста, и при следующем обращении может потребоваться холодный старт. Это начальное состояние всех Durable Object. |
Так Durable Object переходит между этими состояниями (каждое состояние показано в виде прямоугольника со скруглёнными углами).
Если Durable Object не запущен, первый входящий запрос или событие (например, alarm) выполнит constructor() класса Durable Object, а затем выполняет соответствующую вызванную функцию.
На этом этапе Durable Object находится в состоянии активное состояние в оперативной памяти.
После обработки всех входящих запросов или событий Durable Object несколько секунд остаётся неактивным в памяти, находясь либо в состоянии, допускающем переход в спящий режим, либо в состоянии, которое этого не допускает.
Гибернация возможна только если all из перечисленных ниже условий:
- Нет
setTimeout/setIntervalзапланированные колбэки, поскольку после гибернации воссоздать колбэк будет невозможно. - Нет незавершённых ожидаемых
fetch()существует, поскольку считается, что он ожидает ввода-вывода. - Стандартный API WebSocket не используется.
- Ни один запрос или событие больше не обрабатывается, поскольку переход в спящий режим означал бы потерю отслеживания асинхронной функции, которая в конечном счёте должна вернуть ответ на этот запрос.
- Нет активного исходящего TCP-сокета (
connect()) или исходящее WebSocket-соединение.
Если в течение 10 секунд не поступает ни одного запроса или события и выполнены все перечисленные выше условия, Durable Object переходит в состояние переведён в спящий режим состояние.
Если хотя бы одно из перечисленных условий не выполняется, Durable Object остаётся в памяти, в состоянии простаивает, в памяти, не поддерживает гибернацию состояние.
При поступлении запроса или событии, когда объект находится в состоянии переведён в спящий режим состояние, constructor() запустится снова, и Durable Object перейдёт в активное, в оперативной памяти состояние и выполнить вызванную функцию.
Находясь в простаивает, в памяти, не поддерживает гибернацию состояния после 70-140 секунд бездействия (отсутствия входящих запросов или событий) Durable Object будет полностью вытеснен из памяти и, возможно, с хоста Cloudflare, после чего перейдёт в состояние неактивен состояние.
Объекты в переведён в спящий режим состоянии сохраняют подключение своих клиентов Websocket, а среда выполнения сама решает, когда и следует ли переводить объект в состояние неактивен состояние (например, если принято решение перенести объект на другой хост), тем самым перезапуская его жизненный цикл.
Следующий входящий запрос или событие снова запускает этот цикл.
Поведение при завершении работы
Durable Objects периодически завершают работу и перезапускаются, при этом выполняется конструктор класса Durable Object. Это может происходить по разным причинам, включая:
- Новый Worker развертывания с обновлениями кода
- Отсутствие запросов к объекту после переходов состояний, описанных выше
- Обновления Cloudflare для системы выполнения Workers
- Решения Workers runtime о размещении объектов
Когда Durable Object завершает работу, экземпляр объекта автоматически перезапускается, а новые запросы направляются на новый экземпляр. Запросы, уже находящиеся в обработке, обрабатываются следующим образом:
- Запросы HTTP и RPC: выполняемым запросам разрешено завершиться, если они не обращаются к хранилищу Durable Object. Если запрос пытается обратиться к хранилищу Durable Object, он немедленно останавливается и возвращает ошибку, чтобы сохранить свойство глобальной уникальности Durable Objects. Пока система выполнения Worker обновляется, у выполняемых запросов есть до 30 секунд на завершение.
- WebSocket-соединения: запросы WebSocket автоматически завершаются при остановке. Это нужно для того, чтобы новый экземпляр мог как можно быстрее принять соединение.
- Другие вызовы (email, cron): остальные вызовы обрабатываются так же, как запросы HTTP.
Важно убедиться, что любые сервисы, использующие Durable Objects, спроектированы с учётом возможного завершения работы Durable Object.
Обновления кода
Когда код вашего Durable Object обновляется, Worker и Durable Objects развёртываются по всему миру с постепенным достижением согласованности. Это приводит к завершению работы Durable Object с описанным выше поведением. Обновления также могут привести к ситуации, когда запрос попадает на новую версию Worker в одном регионе, а вызовы Durable Object в другом регионе всё ещё обрабатываются предыдущей версией. См. Обновления кода с дополнительной информацией об обработке этого сценария.
Работа без хуков завершения работы
Durable Objects могут завершать работу в любой момент из-за развёртываний, бездействия или решений среды выполнения. Вместо того чтобы полагаться на хуки завершения работы (которые не предоставляются), проектируйте приложение так, чтобы состояние записывалось постепенно.
Cloudflare не предоставляет хуки завершения работы или обратные вызовы жизненного цикла, выполняемые перед остановкой, поскольку не может гарантировать их выполнение во всех случаях, а внешнее программное обеспечение может чрезмерно полагаться на эти (ненадёжные) хуки.
Вместо того чтобы полагаться на хуки завершения работы, регулярно записывайте данные в хранилище, чтобы корректно восстанавливаться после завершения работы.
Например, если вы обрабатываете поток данных и вам нужно сохранять прогресс, записывайте текущую позицию в хранилище по ходу выполнения, а не дожидайтесь завершения, чтобы сохранить её:
// Good: Write progress as you go
async processData(data) {
data.forEach(async (item, index) => {
await this.processItem(item);
// Save progress frequently
await this.ctx.storage.put("lastProcessedIndex", index);
});
}Хотя это может показаться неочевидным, запись в хранилище Durable Object выполняется быстро и синхронно, поэтому вы можете сохранять состояние практически без потерь производительности.
Такой подход гарантирует, что ваш Durable Object сможет безопасно возобновить работу с любой точки, даже если он неожиданно завершит работу.