---
pkg: "@nocobase/preset-cluster"
title: "Подготовка к развёртыванию кластера"
description: "Подготовка к развёртыванию кластера: коммерческие лицензии плагинов (адаптеры PubSub, Queue, Lock, Worker ID), база данных, middleware Redis или RabbitMQ, общее хранилище и балансировка нагрузки."
keywords: "подготовка кластера,коммерческая лицензия,Redis,RabbitMQ,общее хранилище,балансировка нагрузки,Nginx,NocoBase"
---

# Подготовка

Перед развертыванием кластерного приложения необходимо выполнить следующие подготовительные работы.

## Коммерческая лицензия на плагины

Для работы приложения NocoBase в кластерном режиме требуется поддержка следующих плагинов:

| Функция                     | Плагин                                                                              |
| --------------------------- | ----------------------------------------------------------------------------------- |
| Адаптер кэша                | Встроенный                                                                          |
| Адаптер синхронных сигналов | `@nocobase/plugin-pubsub-adapter-redis`                                             |
| Адаптер очереди сообщений   | `@nocobase/plugin-queue-adapter-redis` или `@nocobase/plugin-queue-adapter-rabbitmq` |
| Адаптер распределенной блокировки | `@nocobase/plugin-lock-adapter-redis`                                               |
| Распределитель Worker ID    | `@nocobase/plugin-workerid-allocator-redis`                                         |

Прежде всего, убедитесь, что вы получили лицензии на вышеуказанные плагины (вы можете приобрести соответствующие лицензии через платформу коммерческих плагинов).

## Системные компоненты

Помимо самих экземпляров приложения, развертывание в кластере также требует таких системных компонентов, как база данных, промежуточное ПО, общее хранилище и балансировка нагрузки. Каждая команда может выбрать конкретную реализацию этих компонентов в соответствии со своей собственной эксплуатационной моделью.

### База данных

Поскольку текущий кластерный режим ориентирован только на экземпляры приложений, база данных временно поддерживает только один узел. Если у вас есть архитектура базы данных типа «мастер-подчиненный» (master-slave) или аналогичная, вам потребуется реализовать ее самостоятельно с помощью промежуточного ПО, обеспечив при этом прозрачность для приложения NocoBase.

Если вам требуется warm standby или аварийное восстановление между зонами доступности или регионами, стратегия синхронизации и переключения базы данных должна быть спроектирована и реализована вашей командой эксплуатации.

### Промежуточное ПО

Кластерный режим NocoBase требует использования промежуточного ПО для обеспечения связи и координации между кластерами, включая:

- **Кэш**: Использует распределенное кэширующее промежуточное ПО на базе Redis для повышения скорости доступа к данным.
- **Синхронные сигналы**: Использует функциональность Redis Stream для передачи синхронных сигналов между кластерами.
- **Очередь сообщений**: Использует промежуточное ПО для очередей сообщений на базе Redis или RabbitMQ для асинхронной обработки сообщений.
- **Распределенная блокировка**: Использует распределенную блокировку на базе Redis для обеспечения безопасного доступа к общим ресурсам в кластере.

Если все компоненты промежуточного ПО используют Redis, вы можете запустить единый сервис Redis во внутренней сети кластера (или в Kubernetes). Также можно включить отдельный сервис Redis для каждой функции (кэш, синхронные сигналы, очередь сообщений и распределенная блокировка).

**Рекомендации по версиям**

- Redis: >=8.0 или версия `redis-stack`, включающая функцию Bloom Filter.
- RabbitMQ: >=4.0

### Общее хранилище

NocoBase использует каталог `storage` для хранения системных файлов, и общее хранилище также является обязательным компонентом кластерного развертывания. В многоузловом режиме вы можете выбрать различные реализации в зависимости от своей инфраструктуры, например облачные диски, NFS или EFS, чтобы обеспечить общий доступ между несколькими узлами. В противном случае системные файлы не будут синхронизироваться автоматически, и приложение не сможет работать корректно.

При развертывании с использованием Kubernetes, пожалуйста, обратитесь к разделу [Развертывание в Kubernetes: Общее хранилище](./kubernetes#shared-storage).

#### Что обычно хранится в каталоге `storage`

Содержимое каталога `storage` зависит от включенных плагинов и способа развертывания. Согласно текущей реализации, типичное содержимое включает:

| Путь | Назначение | Рекомендация по использованию |
| --- | --- | --- |
| `storage/uploads` | Загруженные файлы при использовании локального режима хранения | В производственных кластерах следует в первую очередь использовать объектное хранилище, такое как S3 / OSS / COS |
| `storage/plugins` | Локальные пакеты плагинов, устанавливаемые, загружаемые или обнаруживаемые во время выполнения | Если вы зависите от локальных плагинов, этот каталог должен быть общим; если плагины уже встроены в образ, эту зависимость можно уменьшить |
| `storage/apps/<app>/jwt_secret.dat` | Секрет токена по умолчанию, автоматически создаваемый, когда `APP_KEY` явно не задан | Не полагайтесь на этот файл в production; явно задайте `APP_KEY` |
| `storage/apps/<app>/aes_key.dat` | Ключ AES по умолчанию, автоматически создаваемый, когда `APP_AES_SECRET_KEY` явно не задан | Не полагайтесь на этот файл в production; явно задайте `APP_AES_SECRET_KEY` |
| `storage/environment-variables/<app>/aes_key.dat` | Файл ключа AES для сценариев с плагином переменных окружения | Рекомендуется использовать файл ключа, смонтированный только для чтения |
| `storage/logs` | Каталог логов по умолчанию и некоторые журналы миграции | В дальнейшем рекомендуется интеграция с внешней платформой логирования |
| `storage/tmp` | Временные файлы для импорта, экспорта, миграции и т. д. | Может быть временным, но если требуется повторное использование между узлами, его нужно сделать общим, либо выполнять операцию только на одном управляющем узле |
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Артефакты, связанные с резервным копированием, восстановлением и миграцией | Их следует рассматривать как эксплуатационные каталоги, хранить постоянно и не изменять одновременно с нескольких узлов |

Приведенная выше таблица не является исчерпывающей, но она показывает важный момент: в `storage` одновременно находятся бизнес-файлы, файлы ключей, каталоги плагинов, логи и временные артефакты, связанные с эксплуатацией. Поэтому при кластерном развертывании базовым подходом обычно является совместное использование и постоянное хранение всего каталога `/app/nocobase/storage`.

#### Рекомендации по хранению

Согласованность кластера в NocoBase в основном обеспечивается базой данных, Redis, очередями сообщений и распределенными блокировками, а не использованием общей файловой системы в качестве средства координации при высокой конкуренции.

Поэтому рекомендуется:

- Для высокочастотных бизнес-файлов, таких как вложения, отдавать приоритет объектному хранилищу. Долговременная зависимость от локального хранилища в production-кластерах не рекомендуется.
- Использовать общее хранилище в первую очередь для размещения каталога `storage`, а не как высокопроизводительный файловый сервис.
- Такие операции, как установка и обновление плагинов, резервное копирование, восстановление и миграция, выполнять только после сокращения кластера до одного узла; после завершения кластер можно снова масштабировать.

### Балансировка нагрузки

Кластерный режим требует использования балансировщика нагрузки для распределения запросов, а также для проверки работоспособности и обеспечения отказоустойчивости экземпляров приложений. Выбор и настройка этой части осуществляется в соответствии с эксплуатационными потребностями вашей команды.

В качестве примера рассмотрим самостоятельно настроенный Nginx. Добавьте следующее содержимое в файл конфигурации:

```
upstream myapp {
    server 172.31.0.1:13000; # Внутренний узел 1
    server 172.31.0.2:13000; # Внутренний узел 2
    server 172.31.0.3:13000; # Внутренний узел 3
}

server {
    listen 80;

    location / {
        # Использовать определенный upstream для балансировки нагрузки
        proxy_pass http://myapp;
        # ... другие настройки
    }
}
```

Это означает, что запросы будут обратно проксироваться и распределяться между различными узлами сервера для обработки.

Для промежуточного ПО балансировки нагрузки, предоставляемого другими облачными провайдерами, пожалуйста, обратитесь к документации по конфигурации, предоставленной конкретным провайдером.

Для развертываний с высокой доступностью рекомендуется:

- Запускать как минимум 2 экземпляра приложения в рамках одного кластера и поручать балансировщику нагрузки обработку отказов отдельных экземпляров.
- Проверка работоспособности балансировщика нагрузки должна отражать фактическую доступность приложения, а не только факт открытия порта.
- Если вам требуется warm standby между зонами доступности или регионами, обычно следует развернуть несколько независимых кластеров, а команда эксплуатации должна отвечать за синхронизацию и переключение базы данных, общего хранилища и другой инфраструктуры.

## Конфигурация переменных окружения

Все узлы в кластере должны использовать одинаковую конфигурацию переменных окружения. Помимо базовых [переменных окружения](../api/app/env) NocoBase, необходимо также настроить следующие переменные окружения, связанные с промежуточным ПО.

### Ключевые секреты

Помимо переменных окружения промежуточного ПО, все узлы кластера также должны явно настроить одинаковые ключевые секреты:

```ini
APP_KEY=
APP_AES_SECRET_KEY=
# Или использовать файл ключа, смонтированный только для чтения
# APP_AES_SECRET_KEY_PATH=
```

- `APP_KEY` используется для подписи token / JWT. Если он явно не задан, приложение использует резервный файл секрета по умолчанию в каталоге `storage`.
- `APP_AES_SECRET_KEY` используется для расшифровки чувствительных полей в базе данных. Если он явно не задан, приложение также использует резервный файл секрета по умолчанию в каталоге `storage`.
- В эфемерных контейнерах или многоузловых развертываниях зависимость от автоматически созданных локальных файлов ключей может привести к тому, что после перезапуска токены станут недействительными, а исторические зашифрованные данные больше нельзя будет расшифровать.

:::info{title=Совет}
`APP_AES_SECRET_KEY` должен быть 32-байтным ключом AES-256, представленным 64 шестнадцатеричными символами.

В облачных средах рекомендуется централизованно управлять этими значениями через такие сервисы, как Secrets Manager, SSM Parameter Store, Kubernetes Secret или файл ключа, смонтированный только для чтения.
:::

### Многоядерный режим

Когда приложение работает на многоядерном узле, вы можете включить многоядерный режим для этого узла:

```ini
# Включить многоядерный режим PM2
# CLUSTER_MODE=max # Отключено по умолчанию, требуется ручная настройка
```

Если вы развертываете поды приложения в Kubernetes, вы можете игнорировать эту конфигурацию и контролировать количество экземпляров приложения через количество реплик пода.

### Кэш

```ini
# Адаптер кэша, в кластерном режиме необходимо указать redis (по умолчанию используется кэш в памяти, если не указано)
CACHE_DEFAULT_STORE=redis

# URL-адрес подключения адаптера кэша Redis, необходимо указать
CACHE_REDIS_URL=
```

### Синхронные сигналы

```ini
# URL-адрес подключения адаптера синхронизации Redis, по умолчанию redis://localhost:6379/0, если не указано
PUBSUB_ADAPTER_REDIS_URL=
```

### Распределенная блокировка

```ini
# Адаптер блокировки, в кластерном режиме необходимо указать redis (по умолчанию используется локальная блокировка в памяти, если не указано)
LOCK_ADAPTER_DEFAULT=redis

# URL-адрес подключения адаптера блокировки Redis, по умолчанию redis://localhost:6379/0, если не указано
LOCK_ADAPTER_REDIS_URL=
```

### Очередь сообщений

```ini
# Включить Redis в качестве адаптера очереди сообщений (по умолчанию используется адаптер в памяти, если не указано)
QUEUE_ADAPTER=redis
# URL-адрес подключения адаптера очереди сообщений Redis, по умолчанию redis://localhost:6379/0, если не указано
QUEUE_ADAPTER_REDIS_URL=
```

### Распределитель Worker ID

Некоторые системные коллекции в NocoBase используют глобально уникальные ID в качестве первичных ключей. Чтобы избежать конфликтов первичных ключей в кластере, каждый экземпляр приложения должен получить уникальный Worker ID через распределитель Worker ID. Текущий диапазон Worker ID составляет 0–31, что означает, что одно и то же приложение может одновременно работать максимум на 32 узлах. Подробнее о дизайне глобально уникальных ID см. в [@nocobase/snowflake-id](https://github.com/nocobase/nocobase/tree/main/packages/core/snowflake-id).

```ini
# URL-адрес подключения Redis для распределителя Worker ID. Если не указан, будет назначен случайный Worker ID.
REDIS_URL=
```

:::info{title=Совет}
Как правило, все связанные адаптеры могут использовать один и тот же экземпляр Redis, но лучше использовать разные базы данных, чтобы избежать потенциальных конфликтов ключей, например:

```ini
CACHE_REDIS_URL=redis://localhost:6379/0
PUBSUB_ADAPTER_REDIS_URL=redis://localhost:6379/1
LOCK_ADAPTER_REDIS_URL=redis://localhost:6379/2
QUEUE_ADAPTER_REDIS_URL=redis://localhost:6379/3
REDIS_URL=redis://localhost:6379/4
```

В настоящее время каждый плагин использует свои собственные переменные окружения Redis. В будущем мы рассмотрим возможность унификации и использования `REDIS_URL` в качестве резервной конфигурации.

:::

Если вы используете Kubernetes для управления кластером, вы можете настроить вышеуказанные переменные окружения в ConfigMap или Secret. Дополнительную информацию можно найти в разделе [Развертывание в Kubernetes](./kubernetes).

После завершения всех вышеуказанных подготовительных работ вы можете перейти к [процессу эксплуатации](./operations), чтобы продолжить управление экземплярами приложения.
