mirror of
https://github.com/nocobase/nocobase.git
synced 2026-08-30 16:56:07 +08:00
Merge branch 'next' into develop
This commit is contained in:
@@ -5,6 +5,65 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [v2.0.52](https://github.com/nocobase/nocobase/compare/v2.0.51...v2.0.52) - 2026-05-13
|
||||
|
||||
### 🎉 New Features
|
||||
|
||||
- **[client]**
|
||||
- add current user language variable in v2 ([#9405](https://github.com/nocobase/nocobase/pull/9405)) by @katherinehhh
|
||||
|
||||
- add date range limit option for date fields in v2 forms ([#9400](https://github.com/nocobase/nocobase/pull/9400)) by @katherinehhh
|
||||
|
||||
### 🚀 Improvements
|
||||
|
||||
- **[client]** exclude already associated records in association selection dialog of one-to-many table block ([#9448](https://github.com/nocobase/nocobase/pull/9448)) by @katherinehhh
|
||||
|
||||
- **[Departments]** optimize department list style by adding icons and adjusting spacing ([#9435](https://github.com/nocobase/nocobase/pull/9435)) by @katherinehhh
|
||||
|
||||
- **[AI: Knowledge base]** The unique identifier for a knowledge base is configurable at the time of creation by @cgyrock
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **[client]**
|
||||
- Fixed the issue where legacy default value settings can't be removed. ([#9470](https://github.com/nocobase/nocobase/pull/9470)) by @gchust
|
||||
|
||||
- Fixed the issue where can't select options for association's select field. ([#9088](https://github.com/nocobase/nocobase/pull/9088)) by @gchust
|
||||
|
||||
- Fixed an issue where the target block data scope was set incorrectly when deselecting row data in a table block event flow. ([#9443](https://github.com/nocobase/nocobase/pull/9443)) by @gchust
|
||||
|
||||
- Fix duplicate table requests when filter forms have default values ([#9423](https://github.com/nocobase/nocobase/pull/9423)) by @zhangzhonghe
|
||||
|
||||
- Fixed V2 linkage rules to support setting selectable options for fields ([#9399](https://github.com/nocobase/nocobase/pull/9399)) by @jiannx
|
||||
|
||||
- fix error when changing title field of association field in v2 table block ([#9451](https://github.com/nocobase/nocobase/pull/9451)) by @katherinehhh
|
||||
|
||||
- Fixed an intermittent issue where action button linkage rules would fail to take effect. ([#9430](https://github.com/nocobase/nocobase/pull/9430)) by @gchust
|
||||
|
||||
- hide subtable component for to-many association fields in v2 subtable ([#9438](https://github.com/nocobase/nocobase/pull/9438)) by @katherinehhh
|
||||
|
||||
- **[server]** fix(file-manager): force download active content files in local/public storage ([#9437](https://github.com/nocobase/nocobase/pull/9437)) by @mytharcher
|
||||
|
||||
- **[AI employees]** Fixed Ollama test flight requiring key input ([#9450](https://github.com/nocobase/nocobase/pull/9450)) by @cgyrock
|
||||
|
||||
- **[Graph collection manager]** fix graphical interface auto layout throws update action filter error ([#9421](https://github.com/nocobase/nocobase/pull/9421)) by @katherinehhh
|
||||
|
||||
- **[Workflow]** fix: restore helper text in FlowModel workflow binding dialogs for operation and custom action events ([#9447](https://github.com/nocobase/nocobase/pull/9447)) by @mytharcher
|
||||
|
||||
- **[Departments]** fix translation conflict between add user and add department buttons in Users & Permissions settings ([#9456](https://github.com/nocobase/nocobase/pull/9456)) by @katherinehhh
|
||||
|
||||
- **[Collection field: Markdown(Vditor)]** fix markdown field tooltip being hidden in horizontal form layout ([#9420](https://github.com/nocobase/nocobase/pull/9420)) by @katherinehhh
|
||||
|
||||
- **[WEB client]** Fix route type filtering when using translated labels ([#9425](https://github.com/nocobase/nocobase/pull/9425)) by @zhangzhonghe
|
||||
|
||||
- **[Workflow: Approval]**
|
||||
- Fix the issue where JS field appears in approval process settings by @zhangzhonghe
|
||||
|
||||
- Fix approval form layout on mobile devices by @zhangzhonghe
|
||||
|
||||
- Fix duplicate approval record index when delegating approval tasks. by @mytharcher
|
||||
|
||||
- **[Backup manager]** Fixed an issue where backups would fail with an error when files could not be found. by @gchust
|
||||
|
||||
## [v2.0.51](https://github.com/nocobase/nocobase/compare/v2.0.50...v2.0.51) - 2026-05-10
|
||||
|
||||
### 🚀 Improvements
|
||||
|
||||
@@ -5,6 +5,65 @@
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||
并且本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。
|
||||
|
||||
## [v2.0.52](https://github.com/nocobase/nocobase/compare/v2.0.51...v2.0.52) - 2026-05-13
|
||||
|
||||
### 🎉 新特性
|
||||
|
||||
- **[client]**
|
||||
- v2 增加当前用户语言变量 ([#9405](https://github.com/nocobase/nocobase/pull/9405)) by @katherinehhh
|
||||
|
||||
- v2 表单中日期字段增加日期范围限制设置项 ([#9400](https://github.com/nocobase/nocobase/pull/9400)) by @katherinehhh
|
||||
|
||||
### 🚀 优化
|
||||
|
||||
- **[client]** 一对多关系表格区块的关联操作中,弹窗选择区块应排除已关联数据 ([#9448](https://github.com/nocobase/nocobase/pull/9448)) by @katherinehhh
|
||||
|
||||
- **[部门]** 优化部门列表样式,增加图标并调整间距 ([#9435](https://github.com/nocobase/nocobase/pull/9435)) by @katherinehhh
|
||||
|
||||
- **[AI: 知识库]** 支持在创建知识库时指定其唯一键 by @cgyrock
|
||||
|
||||
### 🐛 修复
|
||||
|
||||
- **[client]**
|
||||
- 修复旧默认值配置无法被移除的问题。 ([#9470](https://github.com/nocobase/nocobase/pull/9470)) by @gchust
|
||||
|
||||
- 修复字段赋值里关系字段选择字段无法选择常量字段的问题。 ([#9088](https://github.com/nocobase/nocobase/pull/9088)) by @gchust
|
||||
|
||||
- 修复表格区块事件流行数据取消选择时设置目标区块数据范围不正确的问题。 ([#9443](https://github.com/nocobase/nocobase/pull/9443)) by @gchust
|
||||
|
||||
- 修复筛选表单有默认值时表格初始化重复请求的问题 ([#9423](https://github.com/nocobase/nocobase/pull/9423)) by @zhangzhonghe
|
||||
|
||||
- 修复 V2 联动规则支持字段设置可选项 ([#9399](https://github.com/nocobase/nocobase/pull/9399)) by @jiannx
|
||||
|
||||
- 修复 v2 表格中关系字段修改标题字段时报错的问题 ([#9451](https://github.com/nocobase/nocobase/pull/9451)) by @katherinehhh
|
||||
|
||||
- 修复操作按钮联动规则偶现不生效的问题。 ([#9430](https://github.com/nocobase/nocobase/pull/9430)) by @gchust
|
||||
|
||||
- 修复 v2 子表格中的对多关系字段组件列表出现子表格组件的问题 ([#9438](https://github.com/nocobase/nocobase/pull/9438)) by @katherinehhh
|
||||
|
||||
- **[server]** fix(file-manager): 对本地/公开存储中有风险内容的文件强制下载 ([#9437](https://github.com/nocobase/nocobase/pull/9437)) by @mytharcher
|
||||
|
||||
- **[AI 员工]** 修复 Ollama 试运行无需 Key 却要求输入的问题 ([#9450](https://github.com/nocobase/nocobase/pull/9450)) by @cgyrock
|
||||
|
||||
- **[可视化数据表管理]** 修复 Graphical interface 自动布局报错 “to do update action, filter or filterByTk is required” ([#9421](https://github.com/nocobase/nocobase/pull/9421)) by @katherinehhh
|
||||
|
||||
- **[工作流]** 修复:补回 FlowModel 工作流绑定弹窗中操作类事件与自定义操作事件的提示文案 ([#9447](https://github.com/nocobase/nocobase/pull/9447)) by @mytharcher
|
||||
|
||||
- **[部门]** 修复 Users & Permissions 设置中添加用户和添加部门按钮翻译相互影响的问题 ([#9456](https://github.com/nocobase/nocobase/pull/9456)) by @katherinehhh
|
||||
|
||||
- **[数据表字段:Markdown(Vditor)]** 修复 markdown 字段在表单水平布局时提示信息被遮挡的问题 ([#9420](https://github.com/nocobase/nocobase/pull/9420)) by @katherinehhh
|
||||
|
||||
- **[WEB 客户端]** 修复使用翻译后的路由类型筛选不到数据的问题 ([#9425](https://github.com/nocobase/nocobase/pull/9425)) by @zhangzhonghe
|
||||
|
||||
- **[工作流:审批]**
|
||||
- 修复审批处理设置中显示 JS field 的问题 by @zhangzhonghe
|
||||
|
||||
- 修复移动端审批表单布局显示不正确的问题 by @zhangzhonghe
|
||||
|
||||
- 修复审批转签时审批记录索引重复的问题。 by @mytharcher
|
||||
|
||||
- **[备份管理器]** 修复备份时因为文件无法找到而失败报错的问题。 by @gchust
|
||||
|
||||
## [v2.0.51](https://github.com/nocobase/nocobase/compare/v2.0.50...v2.0.51) - 2026-05-10
|
||||
|
||||
### 🚀 优化
|
||||
|
||||
@@ -9,7 +9,11 @@ keywords: "集群模式,多实例部署,负载均衡,共享存储,Redis,Kubernet
|
||||
|
||||
## 介绍
|
||||
|
||||
NocoBase 自 v1.6.0 版本开始支持以集群模式运行应用。应用以集群模式运行时,可以通过多个实例和使用多核模式来提高应用的对并发访问处理的性能。
|
||||
NocoBase 自 v1.6.0 版本开始支持以集群模式运行应用。应用以集群模式运行时,可以通过多个实例和使用多核模式来提高应用对并发访问处理的性能。
|
||||
|
||||
基于集群模式,可以实现应用层的高可用部署:通过负载均衡将流量分发到同一集群中的多个 NocoBase 实例,在单个实例故障、重启或发布时由其他实例继续对外提供服务。实践中,同一集群通常应部署在同一低延迟网络环境内。
|
||||
|
||||
需要注意的是,NocoBase 集群模式解决的是应用层实例的横向扩展和高可用问题。若需要跨可用区、跨地域的热备或容灾,通常应部署多个独立集群,并由运维团队负责数据库、共享存储及其他基础设施的数据复制与切换策略。
|
||||
|
||||
## 系统架构
|
||||
|
||||
|
||||
@@ -25,12 +25,14 @@ NocoBase 应用以集群方式运行需要基于以下插件支持:
|
||||
|
||||
## 系统组件
|
||||
|
||||
除应用实例本身以外的其他系统组件,根据不同团队的运维需求,可由运维人员自行选用。
|
||||
除应用实例本身以外,集群部署还需要数据库、中间件、共享存储和负载均衡等系统组件。不同团队可按自身运维体系选择这些组件的具体实现方式。
|
||||
|
||||
### 数据库
|
||||
|
||||
由于目前的集群模式只针对应用实例,数据库暂时只支持单节点,如有主从等数据库架构,需要自行通过中间件实现,并保证对 NocoBase 应用透明。
|
||||
|
||||
如需跨可用区或跨地域的热备、容灾能力,数据库同步和切换策略需要由运维团队自行设计和实现。
|
||||
|
||||
### 中间件
|
||||
|
||||
NocoBase 的集群模式需要依赖一些中间件来实现集群间的通信和协调,包括:
|
||||
@@ -49,10 +51,39 @@ NocoBase 的集群模式需要依赖一些中间件来实现集群间的通信
|
||||
|
||||
### 共享存储
|
||||
|
||||
NocoBase 需要使用 storage 目录存储系统相关的文件,在多节点模式下应通过挂载云盘(或 NFS),以支持多节点共享访问。否则本地存储不会自动同步,将无法正常使用。
|
||||
NocoBase 需要使用 storage 目录存储系统相关的文件,也是集群部署的必需组件。在多节点模式下可以根据基础设施环境选择不同实现,例如云盘、NFS、EFS 等,以支持多节点共享访问。否则系统文件不会自动同步,将无法正常使用。
|
||||
|
||||
使用 Kubernetes 部署时,请参考 [Kubernetes 部署:共享存储](./kubernetes#共享存储) 章节。
|
||||
|
||||
#### `storage` 目录通常会保存什么
|
||||
|
||||
`storage` 目录中的内容会随启用的插件和部署方式不同而变化。结合当前实现,常见内容包括:
|
||||
|
||||
| 路径 | 用途 | 使用建议 |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | 本地存储模式下的上传文件 | 生产集群优先改用 S3 / OSS / COS 等对象存储 |
|
||||
| `storage/plugins` | 运行时安装、上传或发现的本地插件包 | 如依赖本地插件,必须共享;如插件已随镜像构建,可减少这部分依赖 |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | 未显式配置 `APP_KEY` 时自动生成的默认 token 密钥 | 生产环境不要依赖该文件,应改为显式配置 `APP_KEY` |
|
||||
| `storage/apps/<app>/aes_key.dat` | 未显式配置 `APP_AES_SECRET_KEY` 时自动生成的 AES 密钥 | 生产环境不要依赖该文件,应改为显式配置 `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、消息队列和分布式锁等机制,而不是把共享文件系统当作高并发协调介质来使用。
|
||||
|
||||
因此建议:
|
||||
|
||||
- 附件等高频业务文件优先使用对象存储,不建议在生产集群中长期依赖本地存储。
|
||||
- 共享存储主要用于承载 `storage` 目录,而不是作为高吞吐文件存储服务。
|
||||
- 插件安装、插件升级、备份、恢复、迁移等操作,需要缩容至单个节点后执行,完成后再扩容。
|
||||
|
||||
如果只是多个节点同时读取同一份上传文件或同一份插件包,共享文件系统通常没有问题;真正需要避免的是多个节点对同一路径进行无序并发写入。
|
||||
|
||||
### 负载均衡
|
||||
|
||||
集群模式需要通过负载均衡器来实现请求的分发,以及应用实例的健康检查和故障转移。该部分根据团队运维需求自行选择和配置。
|
||||
@@ -61,7 +92,6 @@ NocoBase 需要使用 storage 目录存储系统相关的文件,在多节点
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # 可用于会话保持,开启后来自同一客户端的请求总是发送到同一个后端服务器。
|
||||
server 172.31.0.1:13000; # 内网节点1
|
||||
server 172.31.0.2:13000; # 内网节点2
|
||||
server 172.31.0.3:13000; # 内网节点3
|
||||
@@ -82,10 +112,37 @@ server {
|
||||
|
||||
其他云服务商提供的负载均衡中间件可参考具体服务商提供的配置文档。
|
||||
|
||||
对于高可用部署,建议:
|
||||
|
||||
- 在同一集群内至少运行 2 个应用实例,并由负载均衡器负责实例故障切换。
|
||||
- 负载均衡器的健康检查要覆盖应用真实可用性,而不仅是端口存活。
|
||||
- 如需跨可用区或跨地域热备,通常应部署多个独立集群,并由运维团队负责数据库、共享存储等基础设施的数据同步与切换。
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
集群内的所有节点应使用同样的环境变量配置,除 NocoBase 基本的[环境变量](../api/app/env),还需配置以下与中间件相关的环境变量。
|
||||
|
||||
### 关键密钥
|
||||
|
||||
除中间件环境变量外,集群内所有节点还应显式配置相同的关键密钥:
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# 或者使用只读文件挂载
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` 用于 token / JWT 等签名能力。若不显式配置,应用会回退到 `storage` 下的默认密钥文件。
|
||||
- `APP_AES_SECRET_KEY` 用于数据库中敏感字段的 AES 解密。若不显式配置,应用也会回退到 `storage` 下的默认密钥文件。
|
||||
- 对于临时容器或多节点部署,依赖自动生成的本地密钥会导致重启后 token 失效,或历史加密数据无法解密。
|
||||
|
||||
:::info{title=提示}
|
||||
`APP_AES_SECRET_KEY` 需要是一个 32 字节的 AES-256 密钥,对应 64 个十六进制字符。
|
||||
|
||||
在云环境中,推荐通过 Secrets Manager、SSM Parameter Store、Kubernetes Secret 或挂载只读密钥文件的方式统一管理这些值。
|
||||
:::
|
||||
|
||||
### 多核模式
|
||||
|
||||
应用运行在多核节点时,可以开启节点的多核模式:
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "Cluster-Modus,Mehrinstanz,Lastverteilung,gemeinsamer Speicher,Redis,K
|
||||
|
||||
Ab Version v1.6.0 unterstützt NocoBase das Ausführen von Anwendungen im Cluster-Modus. Wenn eine Anwendung im Cluster-Modus läuft, kann sie ihre Leistung bei der Verarbeitung gleichzeitiger Zugriffe verbessern, indem sie mehrere Instanzen und einen Mehrkern-Modus nutzt.
|
||||
|
||||
Auf Basis des Cluster-Modus lässt sich Hochverfügbarkeit auf Anwendungsebene erreichen: Ein Load Balancer verteilt den Datenverkehr auf mehrere NocoBase-Instanzen innerhalb desselben Clusters, sodass bei Ausfall, Neustart oder Bereitstellung einer einzelnen Instanz andere Instanzen den Dienst weiter bereitstellen können. In der Praxis sollte ein einzelner Cluster in der Regel innerhalb derselben Netzwerkumgebung mit geringer Latenz bereitgestellt werden.
|
||||
|
||||
Wichtig ist, dass der Cluster-Modus von NocoBase die horizontale Skalierung und Hochverfügbarkeit von Anwendungsinstanzen auf der Anwendungsebene adressiert. Wenn Sie Warm-Standby oder Disaster Recovery über Verfügbarkeitszonen oder Regionen hinweg benötigen, werden in der Regel mehrere unabhängige Cluster bereitgestellt. Das Betriebsteam ist dann für die Replikations- und Umschaltstrategie von Datenbank, gemeinsamem Speicher und anderer Infrastruktur verantwortlich.
|
||||
|
||||
## Systemarchitektur
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ Dieses Dokument stellt lediglich die grundlegenden Konzepte und Komponenten des
|
||||
- [Betriebsabläufe](./operations)
|
||||
- Erweitert
|
||||
- [Dienstaufteilung](./services-splitting)
|
||||
- [Entwicklerreferenz](./development)
|
||||
- [Entwicklerreferenz](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ Stellen Sie zunächst sicher, dass Sie die Lizenzen für die oben genannten Plug
|
||||
|
||||
## Systemkomponenten
|
||||
|
||||
Neben der Anwendungsinstanz selbst können weitere Systemkomponenten je nach den betrieblichen Anforderungen Ihres Teams vom Betriebspersonal ausgewählt werden.
|
||||
Neben den Anwendungsinstanzen selbst erfordert eine Cluster-Bereitstellung auch Systemkomponenten wie Datenbank, Middleware, gemeinsamen Speicher und Lastverteilung. Unterschiedliche Teams können die konkrete Implementierung dieser Komponenten entsprechend ihrem eigenen Betriebsmodell auswählen.
|
||||
|
||||
### Datenbank
|
||||
|
||||
Da der aktuelle Cluster-Modus nur auf Anwendungsinstanzen abzielt, unterstützt die Datenbank vorübergehend nur einen einzelnen Knoten. Falls Sie eine Datenbankarchitektur wie Master-Slave verwenden, müssen Sie diese selbst über Middleware implementieren und sicherstellen, dass sie für die NocoBase-Anwendung transparent ist.
|
||||
|
||||
Wenn Sie Warm-Standby oder Disaster Recovery über Verfügbarkeitszonen oder Regionen hinweg benötigen, müssen Datenbanksynchronisation und Umschaltstrategie vom Betriebsteam selbst entworfen und umgesetzt werden.
|
||||
|
||||
### Middleware
|
||||
|
||||
Der Cluster-Modus von NocoBase benötigt bestimmte Middleware, um die Kommunikation und Koordination zwischen den Clustern zu ermöglichen. Dazu gehören:
|
||||
@@ -49,10 +51,37 @@ Wenn alle Middleware-Komponenten Redis verwenden, können Sie einen einzelnen Re
|
||||
|
||||
### Gemeinsamer Speicher
|
||||
|
||||
NocoBase benötigt das `storage`-Verzeichnis, um systemrelevante Dateien zu speichern. Im Multi-Node-Modus sollten Sie eine Cloud-Festplatte (oder NFS) mounten, um den gemeinsamen Zugriff über mehrere Knoten hinweg zu ermöglichen. Andernfalls wird der lokale Speicher nicht automatisch synchronisiert und kann nicht ordnungsgemäß funktionieren.
|
||||
NocoBase verwendet das Verzeichnis `storage`, um systemrelevante Dateien zu speichern. Gemeinsamer Speicher ist außerdem ein notwendiger Bestandteil einer Cluster-Bereitstellung. Im Multi-Node-Modus können Sie je nach Infrastruktur unterschiedliche Implementierungen wie Cloud-Datenträger, NFS oder EFS wählen, um den gemeinsamen Zugriff mehrerer Knoten zu ermöglichen. Andernfalls werden Systemdateien nicht automatisch synchronisiert und die Anwendung kann nicht ordnungsgemäß funktionieren.
|
||||
|
||||
Bei der Bereitstellung mit Kubernetes beachten Sie bitte den Abschnitt [Kubernetes-Bereitstellung: Gemeinsamer Speicher](./kubernetes#shared-storage).
|
||||
|
||||
#### Was wird typischerweise im Verzeichnis `storage` gespeichert?
|
||||
|
||||
Der Inhalt des Verzeichnisses `storage` variiert je nach aktivierten Plugins und Bereitstellungsart. Nach aktuellem Implementierungsstand gehören typischerweise dazu:
|
||||
|
||||
| Pfad | Zweck | Nutzungsempfehlung |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | Hochgeladene Dateien im lokalen Speichermodus | In Produktionsclustern sollten vorrangig Objektspeicher wie S3 / OSS / COS verwendet werden |
|
||||
| `storage/plugins` | Zur Laufzeit installierte, hochgeladene oder erkannte lokale Plugin-Pakete | Wenn lokale Plugins verwendet werden, muss dieses Verzeichnis gemeinsam genutzt werden; sind Plugins bereits im Image enthalten, lässt sich diese Abhängigkeit verringern |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | Standard-Token-Schlüssel, der automatisch generiert wird, wenn `APP_KEY` nicht explizit konfiguriert ist | In Produktion nicht auf diese Datei verlassen; stattdessen `APP_KEY` explizit konfigurieren |
|
||||
| `storage/apps/<app>/aes_key.dat` | Standard-AES-Schlüssel, der automatisch generiert wird, wenn `APP_AES_SECRET_KEY` nicht explizit konfiguriert ist | In Produktion nicht auf diese Datei verlassen; stattdessen `APP_AES_SECRET_KEY` explizit konfigurieren |
|
||||
| `storage/environment-variables/<app>/aes_key.dat` | AES-Schlüsseldatei für Szenarien mit dem Umgebungsvariablen-Plugin | Es wird empfohlen, eine schreibgeschützt eingebundene Schlüsseldatei zu verwenden |
|
||||
| `storage/logs` | Standard-Logverzeichnis sowie einige Migrationsprotokolle | Perspektivisch wird die Anbindung an eine externe Logging-Plattform empfohlen |
|
||||
| `storage/tmp` | Temporäre Dateien für Import, Export, Migration usw. | Kann temporär sein; wenn eine Wiederverwendung über mehrere Knoten hinweg nötig ist, muss es gemeinsam genutzt werden oder die Operation auf einen einzelnen Verwaltungs-Knoten beschränkt werden |
|
||||
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Artefakte für Backup, Wiederherstellung und Migration | Diese sollten als Betriebsverzeichnisse betrachtet, persistent gespeichert und nicht gleichzeitig von mehreren Knoten verändert werden |
|
||||
|
||||
Die obige Tabelle ist nicht vollständig, verdeutlicht jedoch einen wichtigen Punkt: `storage` enthält Geschäftsdaten-Dateien, Schlüsseldateien, Plugin-Verzeichnisse, Logs und betriebsbezogene temporäre Artefakte zugleich. Daher ist die übliche Grundlage für Cluster-Bereitstellungen, das gesamte Verzeichnis `/app/nocobase/storage` gemeinsam und persistent bereitzustellen.
|
||||
|
||||
#### Speicherbezogene Empfehlungen
|
||||
|
||||
Die Cluster-Konsistenz in NocoBase stützt sich primär auf Datenbank, Redis, Nachrichtenwarteschlangen und verteilte Sperren und nicht darauf, ein gemeinsames Dateisystem als Koordinationsmedium mit hoher Parallelität zu verwenden.
|
||||
|
||||
Daher wird empfohlen:
|
||||
|
||||
- Für hochfrequent genutzte Geschäftsdaten-Dateien wie Anhänge vorrangig Objektspeicher zu verwenden. Von einer langfristigen Nutzung lokalen Speichers in Produktionsclustern wird abgeraten.
|
||||
- Gemeinsamer Speicher sollte hauptsächlich das Verzeichnis `storage` tragen und nicht als Dateispeicher mit hohem Durchsatz dienen.
|
||||
- Vorgänge wie Plugin-Installation, Plugin-Upgrade, Backup, Wiederherstellung und Migration sollten erst nach dem Herunterskalieren des Clusters auf einen einzelnen Knoten durchgeführt werden; anschließend kann der Cluster wieder hochskaliert werden.
|
||||
|
||||
### Lastverteilung
|
||||
|
||||
Der Cluster-Modus erfordert einen Lastverteiler (Load Balancer), um Anfragen zu verteilen sowie die Integrität der Anwendungsinstanzen zu prüfen und bei Ausfällen zu übernehmen. Dieser Teil sollte entsprechend den betrieblichen Anforderungen Ihres Teams ausgewählt und konfiguriert werden.
|
||||
@@ -61,7 +90,6 @@ Am Beispiel eines selbst gehosteten Nginx fügen Sie den Konfigurationsdateien d
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Kann für die Session-Persistenz verwendet werden. Wenn aktiviert, werden Anfragen desselben Clients immer an denselben Backend-Server gesendet.
|
||||
server 172.31.0.1:13000; # Interner Knoten 1
|
||||
server 172.31.0.2:13000; # Interner Knoten 2
|
||||
server 172.31.0.3:13000; # Interner Knoten 3
|
||||
@@ -82,10 +110,37 @@ Dies bedeutet, dass Anfragen per Reverse-Proxy an verschiedene Serverknoten zur
|
||||
|
||||
Für Lastverteilungs-Middleware, die von anderen Cloud-Anbietern bereitgestellt wird, beachten Sie bitte die Konfigurationsdokumentation des jeweiligen Anbieters.
|
||||
|
||||
Für Hochverfügbarkeits-Bereitstellungen wird empfohlen:
|
||||
|
||||
- Innerhalb desselben Clusters mindestens 2 Anwendungsinstanzen zu betreiben und das Failover einzelner Instanzen dem Load Balancer zu überlassen.
|
||||
- Die Gesundheitsprüfung des Load Balancers sollte die tatsächliche Verfügbarkeit der Anwendung abbilden und nicht nur prüfen, ob der Port erreichbar ist.
|
||||
- Wenn Warm-Standby über Verfügbarkeitszonen oder Regionen hinweg erforderlich ist, sollten in der Regel mehrere unabhängige Cluster bereitgestellt werden. Die Synchronisation und Umschaltung von Datenbank, gemeinsamem Speicher und anderer Infrastruktur liegt dann beim Betriebsteam.
|
||||
|
||||
## Umgebungsvariablen-Konfiguration
|
||||
|
||||
Alle Knoten im Cluster sollten dieselbe Umgebungsvariablen-Konfiguration verwenden. Zusätzlich zu den grundlegenden [Umgebungsvariablen](../api/app/env) von NocoBase müssen auch die folgenden Middleware-bezogenen Umgebungsvariablen konfiguriert werden.
|
||||
|
||||
### Wichtige Schlüssel
|
||||
|
||||
Zusätzlich zu den Middleware-Umgebungsvariablen sollten auf allen Knoten im Cluster dieselben wichtigen Schlüssel explizit konfiguriert werden:
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# Oder eine schreibgeschützt eingebundene Schlüsseldatei verwenden
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` wird für die Signierung von Token / JWT verwendet. Wenn er nicht explizit konfiguriert ist, greift die Anwendung auf die Standard-Schlüsseldatei unter `storage` zurück.
|
||||
- `APP_AES_SECRET_KEY` wird verwendet, um sensible Felder in der Datenbank zu entschlüsseln. Wenn er nicht explizit konfiguriert ist, greift die Anwendung ebenfalls auf die Standard-Schlüsseldatei unter `storage` zurück.
|
||||
- In flüchtigen Containern oder Multi-Node-Bereitstellungen kann die Abhängigkeit von automatisch generierten lokalen Schlüsseldateien dazu führen, dass Tokens nach einem Neustart ungültig werden oder historische verschlüsselte Daten nicht mehr entschlüsselt werden können.
|
||||
|
||||
:::info{title=Tipp}
|
||||
`APP_AES_SECRET_KEY` muss ein 32-Byte-AES-256-Schlüssel sein, dargestellt durch 64 hexadezimale Zeichen.
|
||||
|
||||
In Cloud-Umgebungen wird empfohlen, diese Werte zentral über Dienste wie Secrets Manager, SSM Parameter Store, Kubernetes Secret oder eine schreibgeschützt eingebundene Schlüsseldatei zu verwalten.
|
||||
:::
|
||||
|
||||
### Mehrkern-Modus
|
||||
|
||||
Wenn die Anwendung auf einem Mehrkern-Knoten läuft, können Sie den Mehrkern-Modus des Knotens aktivieren:
|
||||
@@ -160,4 +215,4 @@ Derzeit verwendet jedes Plugin seine eigenen Redis-bezogenen Umgebungsvariablen.
|
||||
|
||||
Wenn Sie Kubernetes zur Verwaltung des Clusters verwenden, können Sie die oben genannten Umgebungsvariablen in einer ConfigMap oder einem Secret konfigurieren. Weitere Informationen finden Sie unter [Kubernetes-Bereitstellung](./kubernetes).
|
||||
|
||||
Nachdem alle oben genannten Vorbereitungen abgeschlossen sind, können Sie mit den [Betriebsabläufen](./operations) fortfahren, um die Anwendungsinstanzen zu verwalten.
|
||||
Nachdem alle oben genannten Vorbereitungen abgeschlossen sind, können Sie mit den [Betriebsabläufen](./operations) fortfahren, um die Anwendungsinstanzen zu verwalten.
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "cluster mode,multi-instance,load balancing,shared storage,Redis,Kuber
|
||||
|
||||
Starting from v1.6.0, NocoBase supports running applications in cluster mode. When an application runs in cluster mode, it can improve its performance in handling concurrent access by using multiple instances and a multi-core mode.
|
||||
|
||||
Based on cluster mode, you can achieve application-level high availability: traffic is distributed by a load balancer across multiple NocoBase instances within the same cluster, so if a single instance fails, restarts, or is being released, other instances can continue serving traffic. In practice, a single cluster should usually be deployed within the same low-latency network environment.
|
||||
|
||||
It is important to note that NocoBase cluster mode addresses horizontal scaling and high availability of application instances at the application layer. If you need warm standby or disaster recovery across availability zones or regions, you would typically deploy multiple independent clusters, and the operations team would be responsible for the data replication and switchover strategy for the database, shared storage, and other infrastructure.
|
||||
|
||||
## System Architecture
|
||||
|
||||
|
||||
@@ -33,4 +37,4 @@ This document only introduces the basic concepts and components of NocoBase's cl
|
||||
- [Operations](./operations)
|
||||
- Advanced
|
||||
- [Service Splitting](./services-splitting)
|
||||
- [Development Reference](./development)
|
||||
- [Development Reference](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ First, please ensure you have obtained licenses for the above plugins (you can p
|
||||
|
||||
## System Components
|
||||
|
||||
Other system components, besides the application instance itself, can be selected by operations personnel based on the team's operational needs.
|
||||
In addition to the application instances themselves, cluster deployment also requires system components such as the database, middleware, shared storage, and load balancing. Different teams can choose the specific implementation of these components based on their own operating model.
|
||||
|
||||
### Database
|
||||
|
||||
Since the current cluster mode only targets application instances, the database temporarily supports only a single node. If you have a database architecture like master-slave, you need to implement it yourself through middleware and ensure it is transparent to the NocoBase application.
|
||||
|
||||
If you need warm standby or disaster recovery across availability zones or regions, the database synchronization and switchover strategy must be designed and implemented by your operations team.
|
||||
|
||||
### Middleware
|
||||
|
||||
NocoBase's cluster mode relies on some middleware to achieve inter-cluster communication and coordination, including:
|
||||
@@ -49,10 +51,37 @@ When all middleware components use Redis, you can start a single Redis service w
|
||||
|
||||
### Shared Storage
|
||||
|
||||
NocoBase needs to use the storage directory to store system-related files. In multi-node mode, you should mount a cloud disk (or NFS) to support shared access across multiple nodes. Otherwise, local storage will not be automatically synchronized, and it will not function properly.
|
||||
NocoBase needs to use the `storage` directory to store system-related files, and shared storage is also a required component of cluster deployment. In multi-node mode, you can choose different implementations based on your infrastructure environment, such as cloud disks, NFS, or EFS, to support shared access across multiple nodes. Otherwise, system files will not be synchronized automatically and the application will not work properly.
|
||||
|
||||
When deploying with Kubernetes, please refer to the [Kubernetes Deployment: Shared Storage](./kubernetes#shared-storage) section.
|
||||
|
||||
#### What is typically stored in the `storage` directory
|
||||
|
||||
The contents of the `storage` directory vary depending on the enabled plugins and the deployment method. Based on the current implementation, common contents include:
|
||||
|
||||
| Path | Purpose | Usage recommendation |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | Uploaded files when using local storage mode | In production clusters, prefer object storage such as S3 / OSS / COS |
|
||||
| `storage/plugins` | Local plugin packages installed, uploaded, or discovered at runtime | If you rely on local plugins, this directory must be shared; if plugins are built into the image, this dependency can be reduced |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | Default token secret generated automatically when `APP_KEY` is not explicitly configured | Do not rely on this file in production; explicitly configure `APP_KEY` instead |
|
||||
| `storage/apps/<app>/aes_key.dat` | Default AES key generated automatically when `APP_AES_SECRET_KEY` is not explicitly configured | Do not rely on this file in production; explicitly configure `APP_AES_SECRET_KEY` instead |
|
||||
| `storage/environment-variables/<app>/aes_key.dat` | AES key file used in environment-variable plugin scenarios | A read-only mounted key file is recommended |
|
||||
| `storage/logs` | Default log directory and some migration logs | It is recommended to integrate with an external logging platform in the future |
|
||||
| `storage/tmp` | Temporary files for import, export, migration, etc. | It can be temporary, but if it needs to be reused across nodes, it must be shared, or the operation should be fixed to a single management node |
|
||||
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Artifacts related to backup, restore, and migration | These should be treated as operations directories, stored persistently, and not modified concurrently across multiple nodes |
|
||||
|
||||
The table above is not exhaustive, but it illustrates an important point: `storage` mixes business files, secret files, plugin directories, logs, and operations-related temporary artifacts. Therefore, in cluster deployment, the baseline is usually to persist and share the entire `/app/nocobase/storage`.
|
||||
|
||||
#### Storage recommendations
|
||||
|
||||
Cluster consistency in NocoBase mainly relies on the database, Redis, message queues, and distributed locks, rather than treating shared file systems as a high-concurrency coordination medium.
|
||||
|
||||
Therefore, the following is recommended:
|
||||
|
||||
- For high-frequency business files such as attachments, prefer object storage. In production clusters, long-term reliance on local storage is not recommended.
|
||||
- Shared storage should mainly be used to host the `storage` directory, rather than as a high-throughput file storage service.
|
||||
- Operations such as plugin installation, plugin upgrade, backup, restore, and migration should be performed only after scaling the cluster down to a single node, and the cluster can be scaled out again after completion.
|
||||
|
||||
### Load Balancing
|
||||
|
||||
Cluster mode requires a load balancer to distribute requests, as well as for health checks and failover of application instances. This part should be selected and configured according to the team's operational needs.
|
||||
@@ -61,7 +90,6 @@ Taking a self-hosted Nginx as an example, add the following content to the confi
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Can be used for session persistence. When enabled, requests from the same client are always sent to the same backend server.
|
||||
server 172.31.0.1:13000; # Internal node 1
|
||||
server 172.31.0.2:13000; # Internal node 2
|
||||
server 172.31.0.3:13000; # Internal node 3
|
||||
@@ -82,10 +110,37 @@ This means that requests are reverse-proxied and distributed to different server
|
||||
|
||||
For load balancing middleware provided by other cloud service providers, please refer to the configuration documentation provided by the specific provider.
|
||||
|
||||
For high-availability deployments, the following is recommended:
|
||||
|
||||
- Run at least 2 application instances within the same cluster, and let the load balancer handle instance failover.
|
||||
- The health check of the load balancer should reflect actual application availability, not just whether the port is open.
|
||||
- If you need warm standby across availability zones or regions, you would typically deploy multiple independent clusters, and the operations team would be responsible for synchronizing and switching the database, shared storage, and other infrastructure.
|
||||
|
||||
## Environment Variable Configuration
|
||||
|
||||
All nodes in the cluster should use the same environment variable configuration. In addition to NocoBase's basic [environment variables](../api/app/env), the following middleware-related environment variables also need to be configured.
|
||||
|
||||
### Key Secrets
|
||||
|
||||
In addition to the middleware environment variables, all nodes in the cluster should also explicitly configure the same key secrets:
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# Or use a read-only mounted key file
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` is used for token / JWT signing. If it is not explicitly configured, the application falls back to the default secret file under `storage`.
|
||||
- `APP_AES_SECRET_KEY` is used to decrypt sensitive fields in the database. If it is not explicitly configured, the application also falls back to the default secret file under `storage`.
|
||||
- In ephemeral containers or multi-node deployments, relying on automatically generated local secret files can cause tokens to become invalid after restart, or historical encrypted data to become undecryptable.
|
||||
|
||||
:::info{title=Tip}
|
||||
`APP_AES_SECRET_KEY` must be a 32-byte AES-256 key, represented by 64 hexadecimal characters.
|
||||
|
||||
In cloud environments, it is recommended to manage these values centrally through services such as Secrets Manager, SSM Parameter Store, Kubernetes Secret, or a read-only mounted key file.
|
||||
:::
|
||||
|
||||
### Multi-core Mode
|
||||
|
||||
When the application runs on a multi-core node, you can enable the node's multi-core mode:
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "modo clúster,multiinstancia,balanceo de carga,almacenamiento compart
|
||||
|
||||
A partir de la versión v1.6.0, NocoBase permite ejecutar aplicaciones en modo de clúster. Cuando una aplicación se ejecuta en este modo, puede mejorar su rendimiento al manejar accesos concurrentes utilizando múltiples instancias y un modo multinúcleo.
|
||||
|
||||
Basándose en el modo clúster, es posible lograr alta disponibilidad a nivel de aplicación: un balanceador de carga distribuye el tráfico entre varias instancias de NocoBase dentro del mismo clúster, de modo que, si una instancia falla, se reinicia o está en proceso de publicación, las demás instancias pueden seguir prestando servicio. En la práctica, un mismo clúster normalmente debe desplegarse dentro del mismo entorno de red de baja latencia.
|
||||
|
||||
Es importante tener en cuenta que el modo clúster de NocoBase resuelve el escalado horizontal y la alta disponibilidad de las instancias de aplicación a nivel de aplicación. Si necesita standby activo/pasivo o recuperación ante desastres entre zonas de disponibilidad o regiones, normalmente deberá desplegar varios clústeres independientes, y el equipo de operaciones será responsable de la estrategia de replicación y conmutación de la base de datos, el almacenamiento compartido y el resto de la infraestructura.
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ Este documento solo presenta los conceptos básicos y los componentes del modo d
|
||||
- [Operaciones](./operations)
|
||||
- Avanzado
|
||||
- [División de servicios](./services-splitting)
|
||||
- [Referencia de desarrollo](./development)
|
||||
- [Referencia de desarrollo](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ Primero, asegúrese de haber obtenido las licencias para los **plugins** mencion
|
||||
|
||||
## Componentes del sistema
|
||||
|
||||
Aparte de la propia instancia de la aplicación, el personal de operaciones puede seleccionar otros componentes del sistema según las necesidades operativas de cada equipo.
|
||||
Además de las propias instancias de la aplicación, una implementación en clúster también requiere componentes del sistema como la base de datos, el middleware, el almacenamiento compartido y el balanceo de carga. Cada equipo puede elegir la implementación concreta de estos componentes según su propio modelo operativo.
|
||||
|
||||
### Base de datos
|
||||
|
||||
Dado que el modo clúster actual se enfoca únicamente en las instancias de la aplicación, la base de datos solo soporta temporalmente un único nodo. Si usted cuenta con una arquitectura de base de datos como maestro-esclavo, deberá implementarla por su cuenta a través de middleware y asegurarse de que sea transparente para la aplicación NocoBase.
|
||||
|
||||
Si necesita standby en caliente o recuperación ante desastres entre zonas de disponibilidad o regiones, la estrategia de sincronización y conmutación de la base de datos debe ser diseñada e implementada por su equipo de operaciones.
|
||||
|
||||
### Middleware
|
||||
|
||||
El modo clúster de NocoBase depende de algunos componentes de middleware para lograr la comunicación y coordinación entre clústeres, incluyendo:
|
||||
@@ -49,10 +51,37 @@ Cuando todos los componentes de middleware utilizan Redis, puede iniciar un úni
|
||||
|
||||
### Almacenamiento compartido
|
||||
|
||||
NocoBase necesita utilizar el directorio `storage` para almacenar archivos relacionados con el sistema. En el modo de múltiples nodos, debe montar un disco en la nube (o NFS) para permitir el acceso compartido entre varios nodos. De lo contrario, el almacenamiento local no se sincronizará automáticamente y no funcionará correctamente.
|
||||
NocoBase necesita utilizar el directorio `storage` para almacenar archivos relacionados con el sistema, y el almacenamiento compartido también es un componente obligatorio del despliegue en clúster. En el modo de múltiples nodos, puede elegir distintas implementaciones según su entorno de infraestructura, como discos en la nube, NFS o EFS, para permitir el acceso compartido entre varios nodos. De lo contrario, los archivos del sistema no se sincronizarán automáticamente y la aplicación no podrá funcionar correctamente.
|
||||
|
||||
Al implementar con Kubernetes, consulte la sección [Implementación en Kubernetes: Almacenamiento compartido](./kubernetes#shared-storage).
|
||||
|
||||
#### Qué suele almacenarse en el directorio `storage`
|
||||
|
||||
El contenido del directorio `storage` varía según los plugins habilitados y el método de despliegue. Según la implementación actual, el contenido habitual incluye:
|
||||
|
||||
| Ruta | Propósito | Recomendación de uso |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | Archivos subidos cuando se usa el modo de almacenamiento local | En clústeres de producción, se recomienda priorizar almacenamiento de objetos como S3 / OSS / COS |
|
||||
| `storage/plugins` | Paquetes de plugins locales instalados, subidos o detectados en tiempo de ejecución | Si depende de plugins locales, este directorio debe compartirse; si los plugins ya están integrados en la imagen, esta dependencia puede reducirse |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | Secreto de token predeterminado generado automáticamente cuando `APP_KEY` no está configurado explícitamente | No dependa de este archivo en producción; configure `APP_KEY` explícitamente |
|
||||
| `storage/apps/<app>/aes_key.dat` | Clave AES predeterminada generada automáticamente cuando `APP_AES_SECRET_KEY` no está configurado explícitamente | No dependa de este archivo en producción; configure `APP_AES_SECRET_KEY` explícitamente |
|
||||
| `storage/environment-variables/<app>/aes_key.dat` | Archivo de clave AES para escenarios del plugin de variables de entorno | Se recomienda montar un archivo de clave en modo solo lectura |
|
||||
| `storage/logs` | Directorio de logs predeterminado y algunos registros de migración | Se recomienda integrar una plataforma de logs externa en el futuro |
|
||||
| `storage/tmp` | Archivos temporales para importación, exportación, migración, etc. | Puede ser temporal, pero si necesita reutilizarse entre nodos, debe compartirse, o bien la operación debe fijarse en un único nodo de administración |
|
||||
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Artefactos relacionados con copia de seguridad, restauración y migración | Deben tratarse como directorios de operaciones, almacenarse de forma persistente y no modificarse de forma concurrente entre varios nodos |
|
||||
|
||||
La tabla anterior no es exhaustiva, pero ilustra un punto importante: `storage` mezcla archivos de negocio, archivos de claves, directorios de plugins, logs y artefactos temporales relacionados con operaciones. Por ello, en los despliegues en clúster, la base habitual es persistir y compartir todo el directorio `/app/nocobase/storage`.
|
||||
|
||||
#### Recomendaciones relacionadas con el almacenamiento
|
||||
|
||||
La consistencia del clúster en NocoBase depende principalmente de la base de datos, Redis, las colas de mensajes y los bloqueos distribuidos, y no de usar el sistema de archivos compartido como medio de coordinación de alta concurrencia.
|
||||
|
||||
Por ello, se recomienda:
|
||||
|
||||
- Para archivos de negocio de alta frecuencia, como los adjuntos, utilizar preferentemente almacenamiento de objetos. No se recomienda depender a largo plazo del almacenamiento local en clústeres de producción.
|
||||
- El almacenamiento compartido debe utilizarse principalmente para alojar el directorio `storage`, y no como un servicio de almacenamiento de archivos de alto rendimiento.
|
||||
- Operaciones como la instalación o actualización de plugins, las copias de seguridad, las restauraciones y las migraciones deben realizarse solo después de reducir el clúster a un único nodo; una vez finalizadas, el clúster puede volver a ampliarse.
|
||||
|
||||
### Balanceo de carga
|
||||
|
||||
El modo clúster requiere un balanceador de carga para distribuir las solicitudes, así como para realizar comprobaciones de estado y conmutación por error de las instancias de la aplicación. Esta parte debe seleccionarse y configurarse según las necesidades operativas de su equipo.
|
||||
@@ -61,7 +90,6 @@ Tomando como ejemplo un Nginx autoalojado, añada el siguiente contenido al arch
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Se puede usar para la persistencia de sesiones. Cuando está habilitado, las solicitudes del mismo cliente siempre se envían al mismo servidor backend.
|
||||
server 172.31.0.1:13000; # Nodo interno 1
|
||||
server 172.31.0.2:13000; # Nodo interno 2
|
||||
server 172.31.0.3:13000; # Nodo interno 3
|
||||
@@ -82,10 +110,37 @@ Esto significa que las solicitudes se reenvían mediante proxy inverso y se dist
|
||||
|
||||
Para el middleware de balanceo de carga proporcionado por otros proveedores de servicios en la nube, consulte la documentación de configuración específica del proveedor.
|
||||
|
||||
Para despliegues de alta disponibilidad, se recomienda:
|
||||
|
||||
- Ejecutar al menos 2 instancias de la aplicación dentro del mismo clúster y dejar que el balanceador de carga se encargue del failover de las instancias.
|
||||
- La verificación de estado del balanceador de carga debe reflejar la disponibilidad real de la aplicación, y no limitarse a comprobar si el puerto está abierto.
|
||||
- Si necesita standby en caliente entre zonas de disponibilidad o regiones, normalmente deberá desplegar varios clústeres independientes, y el equipo de operaciones será responsable de sincronizar y conmutar la base de datos, el almacenamiento compartido y el resto de la infraestructura.
|
||||
|
||||
## Configuración de variables de entorno
|
||||
|
||||
Todos los nodos del clúster deben utilizar la misma configuración de variables de entorno. Además de las [variables de entorno](../api/app/env) básicas de NocoBase, también es necesario configurar las siguientes variables de entorno relacionadas con el middleware.
|
||||
|
||||
### Secretos clave
|
||||
|
||||
Además de las variables de entorno del middleware, todos los nodos del clúster también deben configurar explícitamente los mismos secretos clave:
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# O use un archivo de clave montado en modo solo lectura
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` se utiliza para la firma de tokens / JWT. Si no se configura explícitamente, la aplicación recurre al archivo de secreto predeterminado en `storage`.
|
||||
- `APP_AES_SECRET_KEY` se utiliza para descifrar campos sensibles en la base de datos. Si no se configura explícitamente, la aplicación también recurre al archivo de secreto predeterminado en `storage`.
|
||||
- En contenedores efímeros o despliegues multinodo, depender de archivos de secretos locales generados automáticamente puede hacer que los tokens dejen de ser válidos tras un reinicio o que los datos cifrados históricos ya no puedan descifrarse.
|
||||
|
||||
:::info{title=Consejo}
|
||||
`APP_AES_SECRET_KEY` debe ser una clave AES-256 de 32 bytes, representada por 64 caracteres hexadecimales.
|
||||
|
||||
En entornos en la nube, se recomienda gestionar estos valores de forma centralizada a través de servicios como Secrets Manager, SSM Parameter Store, Kubernetes Secret o un archivo de clave montado en modo solo lectura.
|
||||
:::
|
||||
|
||||
### Modo multinúcleo
|
||||
|
||||
Cuando la aplicación se ejecuta en un nodo multinúcleo, puede habilitar el modo multinúcleo del nodo:
|
||||
@@ -160,4 +215,4 @@ Actualmente, cada **plugin** utiliza sus propias variables de entorno de Redis.
|
||||
|
||||
Si utiliza Kubernetes para gestionar el clúster, puede configurar las variables de entorno mencionadas en un ConfigMap o Secret. Para más información, consulte [Implementación en Kubernetes](./kubernetes).
|
||||
|
||||
Una vez completados todos los preparativos anteriores, puede pasar a los [procesos de operación](./operations) para continuar gestionando las instancias de la aplicación.
|
||||
Una vez completados todos los preparativos anteriores, puede pasar a los [procesos de operación](./operations) para continuar gestionando las instancias de la aplicación.
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "mode cluster,multi-instances,équilibrage de charge,stockage partagé
|
||||
|
||||
Depuis la version v1.6.0, NocoBase prend en charge l'exécution d'applications en mode cluster. Lorsqu'une application s'exécute en mode cluster, elle peut améliorer ses performances dans la gestion des accès concurrents en utilisant plusieurs instances et un mode multi-cœur.
|
||||
|
||||
En s'appuyant sur le mode cluster, il est possible de mettre en place une haute disponibilité au niveau applicatif : un équilibreur de charge distribue le trafic entre plusieurs instances NocoBase au sein d'un même cluster, de sorte que si une instance tombe en panne, redémarre ou est en cours de déploiement, les autres instances peuvent continuer à fournir le service. En pratique, un même cluster doit généralement être déployé dans le même environnement réseau à faible latence.
|
||||
|
||||
Il est important de noter que le mode cluster de NocoBase traite l'extension horizontale et la haute disponibilité des instances applicatives au niveau de l'application. Si vous avez besoin d'un secours à chaud ou d'un plan de reprise après sinistre entre plusieurs zones de disponibilité ou régions, il faut généralement déployer plusieurs clusters indépendants, et l'équipe d'exploitation doit alors prendre en charge la stratégie de réplication et de bascule de la base de données, du stockage partagé et des autres composants d'infrastructure.
|
||||
|
||||
## Architecture système
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ Ce document ne présente que les concepts de base et les composants du mode clus
|
||||
- [Opérations](./operations)
|
||||
- Avancé
|
||||
- [Fractionnement des services](./services-splitting)
|
||||
- [Référence pour les développeurs](./development)
|
||||
- [Référence pour les développeurs](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ Tout d'abord, assurez-vous d'avoir obtenu les licences pour les plugins mentionn
|
||||
|
||||
## Composants système
|
||||
|
||||
En dehors de l'instance d'application elle-même, les autres composants système peuvent être choisis par le personnel d'exploitation en fonction des besoins opérationnels de chaque équipe.
|
||||
En plus des instances applicatives elles-mêmes, un déploiement en cluster nécessite également des composants système tels que la base de données, le middleware, le stockage partagé et l'équilibrage de charge. Chaque équipe peut choisir l'implémentation concrète de ces composants en fonction de son propre modèle d'exploitation.
|
||||
|
||||
### Base de données
|
||||
|
||||
Étant donné que le mode cluster actuel ne concerne que les instances d'application, la base de données ne prend en charge qu'un seul nœud pour le moment. Si vous utilisez une architecture de base de données telle que maître-esclave, vous devrez l'implémenter vous-même via un middleware et vous assurer qu'elle est transparente pour l'application NocoBase.
|
||||
|
||||
Si vous avez besoin d'un secours à chaud ou d'un plan de reprise après sinistre entre plusieurs zones de disponibilité ou régions, la stratégie de synchronisation et de bascule de la base de données doit être conçue et mise en œuvre par votre équipe d'exploitation.
|
||||
|
||||
### Middleware
|
||||
|
||||
Le mode cluster de NocoBase s'appuie sur plusieurs middlewares pour assurer la communication et la coordination entre les clusters, notamment :
|
||||
@@ -49,10 +51,37 @@ Lorsque tous les middlewares utilisent Redis, vous pouvez démarrer un service R
|
||||
|
||||
### Stockage partagé
|
||||
|
||||
NocoBase utilise le répertoire `storage` pour stocker les fichiers système. En mode multi-nœuds, vous devez monter un disque cloud (ou NFS) pour permettre un accès partagé entre les différents nœuds. Sans cela, le stockage local ne sera pas automatiquement synchronisé et l'application ne fonctionnera pas correctement.
|
||||
NocoBase utilise le répertoire `storage` pour stocker les fichiers système, et le stockage partagé constitue également un composant obligatoire d'un déploiement en cluster. En mode multi-nœuds, vous pouvez choisir différentes implémentations selon votre environnement d'infrastructure, telles que des disques cloud, NFS ou EFS, afin de permettre un accès partagé entre plusieurs nœuds. Sans cela, les fichiers système ne seront pas synchronisés automatiquement et l'application ne pourra pas fonctionner correctement.
|
||||
|
||||
Lors d'un déploiement avec Kubernetes, veuillez consulter la section [Déploiement Kubernetes : Stockage partagé](./kubernetes#shared-storage).
|
||||
|
||||
#### Que trouve-t-on généralement dans le répertoire `storage` ?
|
||||
|
||||
Le contenu du répertoire `storage` varie selon les plugins activés et le mode de déploiement. D'après l'implémentation actuelle, on y trouve généralement :
|
||||
|
||||
| Chemin | Usage | Recommandation d'utilisation |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | Fichiers téléversés lorsque le mode de stockage local est utilisé | Dans les clusters de production, privilégiez un stockage objet tel que S3 / OSS / COS |
|
||||
| `storage/plugins` | Paquets de plugins locaux installés, téléversés ou détectés à l'exécution | Si vous dépendez de plugins locaux, ce répertoire doit être partagé ; si les plugins sont déjà intégrés à l'image, cette dépendance peut être réduite |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | Secret de jeton par défaut généré automatiquement lorsque `APP_KEY` n'est pas configuré explicitement | Ne vous appuyez pas sur ce fichier en production ; configurez explicitement `APP_KEY` |
|
||||
| `storage/apps/<app>/aes_key.dat` | Clé AES par défaut générée automatiquement lorsque `APP_AES_SECRET_KEY` n'est pas configuré explicitement | Ne vous appuyez pas sur ce fichier en production ; configurez explicitement `APP_AES_SECRET_KEY` |
|
||||
| `storage/environment-variables/<app>/aes_key.dat` | Fichier de clé AES pour les scénarios liés au plugin de variables d'environnement | Il est recommandé de monter un fichier de clé en lecture seule |
|
||||
| `storage/logs` | Répertoire de logs par défaut et certains journaux de migration | Il est recommandé d'intégrer une plateforme de logs externe à l'avenir |
|
||||
| `storage/tmp` | Fichiers temporaires pour l'import, l'export, la migration, etc. | Peut être temporaire, mais s'il doit être réutilisé entre plusieurs nœuds, il doit être partagé, ou bien l'opération doit être limitée à un seul nœud d'administration |
|
||||
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Artefacts liés à la sauvegarde, à la restauration et à la migration | Ils doivent être considérés comme des répertoires d'exploitation, stockés de manière persistante et non modifiés de manière concurrente par plusieurs nœuds |
|
||||
|
||||
Le tableau ci-dessus n'est pas exhaustif, mais il illustre un point important : `storage` regroupe à la fois des fichiers métier, des fichiers de clés, des répertoires de plugins, des logs et des artefacts temporaires liés à l'exploitation. Par conséquent, dans un déploiement en cluster, la base habituelle consiste à partager et persister l'ensemble du répertoire `/app/nocobase/storage`.
|
||||
|
||||
#### Recommandations relatives au stockage
|
||||
|
||||
La cohérence du cluster dans NocoBase repose principalement sur la base de données, Redis, les files de messages et les verrous distribués, et non sur l'utilisation du système de fichiers partagé comme mécanisme de coordination à haute concurrence.
|
||||
|
||||
Par conséquent, il est recommandé :
|
||||
|
||||
- Pour les fichiers métier à forte fréquence tels que les pièces jointes, de privilégier un stockage objet. Il n'est pas recommandé de dépendre à long terme du stockage local dans les clusters de production.
|
||||
- D'utiliser le stockage partagé principalement pour héberger le répertoire `storage`, et non comme service de stockage de fichiers à haut débit.
|
||||
- D'effectuer les opérations telles que l'installation ou la mise à niveau de plugins, les sauvegardes, les restaurations et les migrations uniquement après avoir réduit le cluster à un seul nœud ; une fois l'opération terminée, le cluster peut être remis à l'échelle.
|
||||
|
||||
### Équilibrage de charge
|
||||
|
||||
Le mode cluster nécessite un équilibreur de charge pour distribuer les requêtes, effectuer les vérifications de santé des instances d'application et gérer le basculement en cas de défaillance. Cette partie doit être choisie et configurée en fonction des besoins opérationnels de votre équipe.
|
||||
@@ -61,7 +90,6 @@ Le mode cluster nécessite un équilibreur de charge pour distribuer les requêt
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Peut être utilisé pour la persistance de session. Une fois activé, les requêtes provenant du même client sont toujours envoyées au même serveur backend.
|
||||
server 172.31.0.1:13000; # Nœud interne 1
|
||||
server 172.31.0.2:13000; # Nœud interne 2
|
||||
server 172.31.0.3:13000; # Nœud interne 3
|
||||
@@ -82,10 +110,37 @@ Cela signifie que les requêtes sont redirigées et distribuées aux différents
|
||||
|
||||
Pour les middlewares d'équilibrage de charge fournis par d'autres fournisseurs de services cloud, veuillez consulter la documentation de configuration spécifique à chaque fournisseur.
|
||||
|
||||
Pour les déploiements à haute disponibilité, il est recommandé :
|
||||
|
||||
- D'exécuter au moins 2 instances applicatives au sein d'un même cluster et de laisser l'équilibreur de charge gérer le basculement des instances.
|
||||
- Que la vérification d'état de l'équilibreur de charge reflète la disponibilité réelle de l'application, et pas seulement l'ouverture du port.
|
||||
- Si vous avez besoin d'un secours à chaud entre plusieurs zones de disponibilité ou régions, il faut généralement déployer plusieurs clusters indépendants, et l'équipe d'exploitation doit prendre en charge la synchronisation et la bascule de la base de données, du stockage partagé et du reste de l'infrastructure.
|
||||
|
||||
## Configuration des variables d'environnement
|
||||
|
||||
Tous les nœuds du cluster doivent utiliser la même configuration de variables d'environnement. En plus des [variables d'environnement](../api/app/env) de base de NocoBase, vous devez également configurer les variables d'environnement suivantes, liées aux middlewares.
|
||||
|
||||
### Secrets clés
|
||||
|
||||
En plus des variables d'environnement liées au middleware, tous les nœuds du cluster doivent également configurer explicitement les mêmes secrets clés :
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# Ou utiliser un fichier de clé monté en lecture seule
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` est utilisé pour la signature des tokens / JWT. S'il n'est pas configuré explicitement, l'application utilise le fichier de secret par défaut situé dans `storage`.
|
||||
- `APP_AES_SECRET_KEY` est utilisé pour déchiffrer les champs sensibles dans la base de données. S'il n'est pas configuré explicitement, l'application utilise également le fichier de secret par défaut situé dans `storage`.
|
||||
- Dans des conteneurs éphémères ou des déploiements multi-nœuds, le fait de dépendre de fichiers de secrets locaux générés automatiquement peut rendre les tokens invalides après un redémarrage ou empêcher le déchiffrement des données historiques chiffrées.
|
||||
|
||||
:::info{title=Conseil}
|
||||
`APP_AES_SECRET_KEY` doit être une clé AES-256 de 32 octets, représentée par 64 caractères hexadécimaux.
|
||||
|
||||
Dans les environnements cloud, il est recommandé de gérer centralement ces valeurs via des services tels que Secrets Manager, SSM Parameter Store, Kubernetes Secret ou un fichier de clé monté en lecture seule.
|
||||
:::
|
||||
|
||||
### Mode multi-cœur
|
||||
|
||||
Lorsque l'application s'exécute sur un nœud multi-cœur, vous pouvez activer le mode multi-cœur du nœud :
|
||||
@@ -160,4 +215,4 @@ Actuellement, chaque plugin utilise ses propres variables d'environnement liées
|
||||
|
||||
Si vous utilisez Kubernetes pour gérer votre cluster, vous pouvez configurer les variables d'environnement ci-dessus dans un ConfigMap ou un Secret. Pour plus d'informations, veuillez consulter [Déploiement Kubernetes](./kubernetes).
|
||||
|
||||
Une fois tous les préparatifs ci-dessus terminés, vous pouvez passer aux [Opérations](./operations) pour continuer à gérer les instances de l'application.
|
||||
Une fois tous les préparatifs ci-dessus terminés, vous pouvez passer aux [Opérations](./operations) pour continuer à gérer les instances de l'application.
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "クラスターモード,マルチインスタンス,負荷分散,共
|
||||
|
||||
NocoBaseはv1.6.0以降、アプリケーションをクラスターモードで実行できるようになりました。アプリケーションをクラスターモードで実行すると、複数のインスタンスとマルチコアモードを活用することで、同時アクセス処理のパフォーマンスを向上させることができます。
|
||||
|
||||
クラスターモードを基盤として、アプリケーションレベルの高可用性を実現できます。ロードバランサーが同一クラスター内の複数のNocoBaseインスタンスにトラフィックを分散することで、単一インスタンスが障害・再起動・リリース中であっても、他のインスタンスが継続してサービスを提供できます。実運用では、同一クラスターは通常、同じ低遅延のネットワーク環境内に配置する必要があります。
|
||||
|
||||
なお、NocoBaseのクラスターモードが扱うのは、アプリケーション層におけるインスタンスの水平拡張と高可用性です。可用性ゾーンやリージョンをまたぐウォームスタンバイや災害復旧が必要な場合は、通常は複数の独立したクラスターを配置し、データベース、共有ストレージ、その他インフラのデータ複製および切り替え戦略は運用チームが設計・実装する必要があります。
|
||||
|
||||
## システムアーキテクチャ
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ NocoBaseはv1.6.0以降、アプリケーションをクラスターモードで
|
||||
- [運用手順](./operations)
|
||||
- 高度な設定
|
||||
- [サービス分割](./services-splitting)
|
||||
- [開発者向けリファレンス](./development)
|
||||
- [開発者向けリファレンス](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ NocoBaseアプリケーションをクラスターモードで実行するには
|
||||
|
||||
## システムコンポーネント
|
||||
|
||||
アプリケーションインスタンス自体を除く他のシステムコンポーネントは、各チームの運用要件に応じて、運用担当者が自由に選択できます。
|
||||
アプリケーションインスタンス自体に加えて、クラスター配備にはデータベース、ミドルウェア、共有ストレージ、ロードバランシングなどのシステムコンポーネントも必要です。これらのコンポーネントの具体的な実装は、各チームが自社の運用体制に応じて選択できます。
|
||||
|
||||
### データベース
|
||||
|
||||
現在のクラスターモードはアプリケーションインスタンスのみを対象としているため、データベースは一時的にシングルノードのみをサポートしています。もしマスター・スレーブなどのデータベースアーキテクチャをお持ちの場合は、ミドルウェアを介してご自身で実装し、NocoBaseアプリケーションに対して透過的であることを保証する必要があります。
|
||||
|
||||
可用性ゾーンやリージョンをまたぐウォームスタンバイや災害復旧が必要な場合、データベースの同期および切り替え戦略は運用チーム自身が設計・実装する必要があります。
|
||||
|
||||
### ミドルウェア
|
||||
|
||||
NocoBaseのクラスターモードは、クラスター間の通信と連携を実現するために、いくつかのミドルウェアに依存しています。これには以下が含まれます。
|
||||
@@ -49,10 +51,37 @@ NocoBaseのクラスターモードは、クラスター間の通信と連携を
|
||||
|
||||
### 共有ストレージ
|
||||
|
||||
NocoBaseは、システム関連ファイルを`storage`ディレクトリに保存する必要があります。マルチノードモードでは、複数のノード間で共有アクセスをサポートするために、クラウドディスク(またはNFS)をマウントする必要があります。そうしないと、ローカルストレージは自動的に同期されず、正常に機能しません。
|
||||
NocoBaseは、システム関連ファイルを保存するために`storage`ディレクトリを使用します。また、共有ストレージはクラスター配備における必須コンポーネントでもあります。マルチノードモードでは、複数ノード間の共有アクセスを実現するために、インフラ環境に応じてクラウドディスク、NFS、EFSなどの実装を選択できます。そうしないと、システムファイルは自動的に同期されず、アプリケーションは正常に動作しません。
|
||||
|
||||
Kubernetesでデプロイする場合は、[Kubernetesデプロイ:共有ストレージ](./kubernetes#共有ストレージ)の章を参照してください。
|
||||
|
||||
#### `storage` ディレクトリには通常何が保存されるか
|
||||
|
||||
`storage` ディレクトリの内容は、有効化されているプラグインやデプロイ方式によって異なります。現在の実装に基づく代表的な内容は以下のとおりです。
|
||||
|
||||
| パス | 用途 | 利用上の推奨 |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | ローカルストレージモードでアップロードされたファイル | 本番クラスターでは S3 / OSS / COS などのオブジェクトストレージを優先してください |
|
||||
| `storage/plugins` | 実行時にインストール、アップロード、または検出されるローカルプラグインパッケージ | ローカルプラグインに依存する場合は共有が必須です。プラグインがイメージに組み込まれていれば、この依存は減らせます |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | `APP_KEY` が明示設定されていない場合に自動生成されるデフォルトのトークン秘密鍵 | 本番環境ではこのファイルに依存せず、`APP_KEY` を明示的に設定してください |
|
||||
| `storage/apps/<app>/aes_key.dat` | `APP_AES_SECRET_KEY` が明示設定されていない場合に自動生成されるデフォルトの AES 鍵 | 本番環境ではこのファイルに依存せず、`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、メッセージキュー、分散ロックによって担保されており、共有ファイルシステムを高並行な調整媒体として使う前提ではありません。
|
||||
|
||||
そのため、以下を推奨します。
|
||||
|
||||
- 添付ファイルのような高頻度な業務ファイルは、オブジェクトストレージを優先してください。本番クラスターでローカルストレージに長期依存することは推奨されません。
|
||||
- 共有ストレージは主に `storage` ディレクトリを保持するために使用し、高スループットなファイルストレージサービスとしては扱わないでください。
|
||||
- プラグインのインストール、プラグインのアップグレード、バックアップ、リストア、マイグレーションなどの操作は、クラスターを単一ノードまで縮退させてから実施し、完了後に再度スケールアウトしてください。
|
||||
|
||||
### ロードバランシング
|
||||
|
||||
クラスターモードでは、リクエストの分散、アプリケーションインスタンスのヘルスチェック、およびフェイルオーバーを実現するために、ロードバランサーが必要です。この部分は、チームの運用要件に応じてご自身で選択・設定してください。
|
||||
@@ -61,7 +90,6 @@ Kubernetesでデプロイする場合は、[Kubernetesデプロイ:共有ス
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # セッション維持に使用できます。有効にすると、同じクライアントからのリクエストは常に同じバックエンドサーバーに送信されます。
|
||||
server 172.31.0.1:13000; # 内部ノード1
|
||||
server 172.31.0.2:13000; # 内部ノード2
|
||||
server 172.31.0.3:13000; # 内部ノード3
|
||||
@@ -82,10 +110,37 @@ server {
|
||||
|
||||
他のクラウドサービスプロバイダーが提供するロードバランシングミドルウェアについては、各プロバイダーが提供する設定ドキュメントを参照してください。
|
||||
|
||||
高可用性を前提とした配備では、以下を推奨します。
|
||||
|
||||
- 同一クラスター内で少なくとも 2 つのアプリケーションインスタンスを稼働させ、インスタンス障害時のフェイルオーバーはロードバランサーに任せてください。
|
||||
- ロードバランサーのヘルスチェックは、単にポートが開いているかではなく、アプリケーションの実際の可用性を反映するようにしてください。
|
||||
- 可用性ゾーンやリージョンをまたぐウォームスタンバイが必要な場合は、通常は複数の独立したクラスターを配備し、データベース、共有ストレージ、その他インフラの同期と切り替えは運用チームが担当します。
|
||||
|
||||
## 環境変数設定
|
||||
|
||||
クラスター内のすべてのノードは、同じ環境変数設定を使用する必要があります。NocoBaseの基本的な[環境変数](../api/app/env)に加えて、以下のミドルウェア関連の環境変数も設定する必要があります。
|
||||
|
||||
### 重要な鍵
|
||||
|
||||
ミドルウェア関連の環境変数に加えて、クラスター内のすべてのノードでは、以下の重要な鍵も同一の値で明示的に設定する必要があります。
|
||||
|
||||
```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 文字の 16 進文字列で表現する必要があります。
|
||||
|
||||
クラウド環境では、Secrets Manager、SSM Parameter Store、Kubernetes Secret、または読み取り専用でマウントした鍵ファイルなどを使って、これらの値を一元管理することを推奨します。
|
||||
:::
|
||||
|
||||
### マルチコアモード
|
||||
|
||||
アプリケーションがマルチコアノードで実行される場合、ノードのマルチコアモードを有効にできます。
|
||||
@@ -159,4 +214,4 @@ REDIS_URL=redis://localhost:6379/4
|
||||
|
||||
Kubernetesを使用してクラスターを管理する場合、上記の環境変数をConfigMapまたはSecretに設定できます。詳細については、[Kubernetesデプロイ](./kubernetes)を参照してください。
|
||||
|
||||
上記のすべての準備作業が完了したら、[運用プロセス](./operations)に進み、アプリケーションインスタンスの管理を続行できます。
|
||||
上記のすべての準備作業が完了したら、[運用プロセス](./operations)に進み、アプリケーションインスタンスの管理を続行できます。
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "modo cluster,multi-instância,balanceamento de carga,armazenamento co
|
||||
|
||||
A partir da versão v1.6.0, o NocoBase passou a suportar a execução de aplicações em modo de cluster. Ao rodar uma aplicação nesse modo, você pode melhorar o desempenho no tratamento de acessos concorrentes, utilizando múltiplas instâncias e o modo multi-core.
|
||||
|
||||
Com base no modo de cluster, é possível alcançar alta disponibilidade no nível da aplicação: um balanceador de carga distribui o tráfego entre várias instâncias do NocoBase dentro do mesmo cluster, de modo que, se uma instância falhar, reiniciar ou estiver em processo de publicação, as demais instâncias podem continuar atendendo. Na prática, um mesmo cluster normalmente deve ser implantado dentro do mesmo ambiente de rede de baixa latência.
|
||||
|
||||
É importante observar que o modo de cluster do NocoBase trata da escalabilidade horizontal e da alta disponibilidade das instâncias da aplicação no nível da aplicação. Se você precisar de warm standby ou recuperação de desastres entre zonas de disponibilidade ou regiões, normalmente deverá implantar vários clusters independentes, e a equipe de operações será responsável pela estratégia de replicação e comutação do banco de dados, do armazenamento compartilhado e da infraestrutura restante.
|
||||
|
||||
## Arquitetura do Sistema
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ Este documento apresenta apenas os conceitos básicos e os componentes do modo d
|
||||
- [Operações](./operations)
|
||||
- Avançado
|
||||
- [Divisão de Serviços](./services-splitting)
|
||||
- [Referência de Desenvolvimento](./development)
|
||||
- [Referência de Desenvolvimento](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ Primeiro, certifique-se de ter obtido as licenças para os plugins acima (você
|
||||
|
||||
## Componentes do Sistema
|
||||
|
||||
Outros componentes do sistema, além da própria instância do aplicativo, podem ser selecionados pela equipe de operações com base nas necessidades operacionais de cada time.
|
||||
Além das próprias instâncias da aplicação, uma implantação em cluster também requer componentes de sistema como banco de dados, middleware, armazenamento compartilhado e balanceamento de carga. Cada equipe pode escolher a implementação concreta desses componentes de acordo com o seu próprio modelo operacional.
|
||||
|
||||
### Banco de Dados
|
||||
|
||||
Como o modo de cluster atual se concentra apenas nas instâncias do aplicativo, o banco de dados, por enquanto, suporta apenas um único nó. Se você tiver uma arquitetura de banco de dados como mestre-escravo, precisará implementá-la por conta própria através de um middleware e garantir que seja transparente para o aplicativo NocoBase.
|
||||
|
||||
Se você precisar de warm standby ou recuperação de desastres entre zonas de disponibilidade ou regiões, a estratégia de sincronização e comutação do banco de dados deverá ser projetada e implementada pela sua equipe de operações.
|
||||
|
||||
### Middleware
|
||||
|
||||
O modo de cluster do NocoBase depende de alguns middlewares para comunicação e coordenação entre os clusters, incluindo:
|
||||
@@ -49,10 +51,37 @@ Quando todos os componentes de middleware utilizam Redis, você pode iniciar um
|
||||
|
||||
### Armazenamento Compartilhado
|
||||
|
||||
O NocoBase precisa usar o diretório `storage` para armazenar arquivos relacionados ao sistema. No modo de múltiplos nós, você deve montar um disco na nuvem (ou NFS) para suportar o acesso compartilhado entre os vários nós. Caso contrário, o armazenamento local não será sincronizado automaticamente e não funcionará corretamente.
|
||||
O NocoBase precisa usar o diretório `storage` para armazenar arquivos relacionados ao sistema, e o armazenamento compartilhado também é um componente obrigatório de uma implantação em cluster. No modo de múltiplos nós, você pode escolher diferentes implementações de acordo com o ambiente de infraestrutura, como discos em nuvem, NFS ou EFS, para suportar o acesso compartilhado entre vários nós. Caso contrário, os arquivos do sistema não serão sincronizados automaticamente e a aplicação não funcionará corretamente.
|
||||
|
||||
Ao implantar com Kubernetes, consulte a seção [Implantação Kubernetes: Armazenamento Compartilhado](./kubernetes#shared-storage).
|
||||
|
||||
#### O que normalmente é armazenado no diretório `storage`
|
||||
|
||||
O conteúdo do diretório `storage` varia de acordo com os plugins habilitados e a forma de implantação. Com base na implementação atual, os conteúdos mais comuns incluem:
|
||||
|
||||
| Caminho | Finalidade | Recomendação de uso |
|
||||
| --- | --- | --- |
|
||||
| `storage/uploads` | Arquivos enviados quando o modo de armazenamento local é usado | Em clusters de produção, priorize armazenamento de objetos como S3 / OSS / COS |
|
||||
| `storage/plugins` | Pacotes de plugins locais instalados, enviados ou descobertos em tempo de execução | Se você depende de plugins locais, este diretório precisa ser compartilhado; se os plugins já estiverem embutidos na imagem, essa dependência pode ser reduzida |
|
||||
| `storage/apps/<app>/jwt_secret.dat` | Segredo padrão de token gerado automaticamente quando `APP_KEY` não está configurado explicitamente | Não dependa deste arquivo em produção; configure `APP_KEY` explicitamente |
|
||||
| `storage/apps/<app>/aes_key.dat` | Chave AES padrão gerada automaticamente quando `APP_AES_SECRET_KEY` não está configurado explicitamente | Não dependa deste arquivo em produção; configure `APP_AES_SECRET_KEY` explicitamente |
|
||||
| `storage/environment-variables/<app>/aes_key.dat` | Arquivo de chave AES usado em cenários do plugin de variáveis de ambiente | Recomenda-se montar um arquivo de chave em modo somente leitura |
|
||||
| `storage/logs` | Diretório padrão de logs e alguns registros de migração | Recomenda-se integrar uma plataforma externa de logs no futuro |
|
||||
| `storage/tmp` | Arquivos temporários para importação, exportação, migração etc. | Pode ser temporário, mas se precisar ser reutilizado entre nós, deve ser compartilhado, ou a operação deve ser fixada em um único nó de administração |
|
||||
| `storage/backups`, `storage/duplicator`, `storage/migration-manager` | Artefatos relacionados a backup, restauração e migração | Devem ser tratados como diretórios operacionais, armazenados de forma persistente e não modificados de forma concorrente por vários nós |
|
||||
|
||||
A tabela acima não é exaustiva, mas mostra um ponto importante: `storage` mistura arquivos de negócio, arquivos de chaves, diretórios de plugins, logs e artefatos temporários relacionados à operação. Por isso, em implantações em cluster, a prática básica costuma ser compartilhar e persistir todo o diretório `/app/nocobase/storage`.
|
||||
|
||||
#### Recomendações relacionadas ao armazenamento
|
||||
|
||||
A consistência de cluster no NocoBase depende principalmente do banco de dados, do Redis, das filas de mensagens e dos bloqueios distribuídos, e não de usar o sistema de arquivos compartilhado como meio de coordenação de alta concorrência.
|
||||
|
||||
Portanto, recomenda-se:
|
||||
|
||||
- Para arquivos de negócio de alta frequência, como anexos, priorize armazenamento de objetos. Não é recomendável depender de armazenamento local por longo prazo em clusters de produção.
|
||||
- O armazenamento compartilhado deve ser usado principalmente para hospedar o diretório `storage`, e não como um serviço de armazenamento de arquivos de alta vazão.
|
||||
- Operações como instalação e atualização de plugins, backup, restauração e migração devem ser realizadas somente após reduzir o cluster para um único nó; após a conclusão, o cluster pode ser escalado novamente.
|
||||
|
||||
### Balanceamento de Carga
|
||||
|
||||
O modo de cluster exige um balanceador de carga para distribuir as requisições, realizar verificações de saúde das instâncias do aplicativo e gerenciar o failover. Esta parte deve ser selecionada e configurada de acordo com as necessidades operacionais da sua equipe.
|
||||
@@ -61,7 +90,6 @@ Tomando um Nginx auto-hospedado como exemplo, adicione o seguinte conteúdo ao a
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Pode ser usado para persistência de sessão. Quando ativado, as requisições do mesmo cliente são sempre enviadas para o mesmo servidor backend.
|
||||
server 172.31.0.1:13000; # Nó interno 1
|
||||
server 172.31.0.2:13000; # Nó interno 2
|
||||
server 172.31.0.3:13000; # Nó interno 3
|
||||
@@ -82,10 +110,37 @@ Isso significa que as requisições são encaminhadas por proxy reverso e distri
|
||||
|
||||
Para middlewares de balanceamento de carga fornecidos por outros provedores de serviços em nuvem, consulte a documentação de configuração específica do provedor.
|
||||
|
||||
Para implantações de alta disponibilidade, recomenda-se:
|
||||
|
||||
- Executar pelo menos 2 instâncias da aplicação dentro do mesmo cluster e deixar que o balanceador de carga cuide do failover das instâncias.
|
||||
- A verificação de saúde do balanceador de carga deve refletir a disponibilidade real da aplicação, e não apenas se a porta está aberta.
|
||||
- Se você precisar de warm standby entre zonas de disponibilidade ou regiões, normalmente deverá implantar vários clusters independentes, e a equipe de operações será responsável pela sincronização e comutação do banco de dados, do armazenamento compartilhado e da infraestrutura restante.
|
||||
|
||||
## Configuração de Variáveis de Ambiente
|
||||
|
||||
Todos os nós no cluster devem usar a mesma configuração de variáveis de ambiente. Além das [variáveis de ambiente](../api/app/env) básicas do NocoBase, você também precisará configurar as seguintes variáveis de ambiente relacionadas ao middleware.
|
||||
|
||||
### Segredos principais
|
||||
|
||||
Além das variáveis de ambiente do middleware, todos os nós do cluster também devem configurar explicitamente os mesmos segredos principais:
|
||||
|
||||
```ini
|
||||
APP_KEY=
|
||||
APP_AES_SECRET_KEY=
|
||||
# Ou use um arquivo de chave montado em modo somente leitura
|
||||
# APP_AES_SECRET_KEY_PATH=
|
||||
```
|
||||
|
||||
- `APP_KEY` é usado para a assinatura de tokens / JWT. Se não for configurado explicitamente, a aplicação recorrerá ao arquivo de segredo padrão em `storage`.
|
||||
- `APP_AES_SECRET_KEY` é usado para descriptografar campos sensíveis no banco de dados. Se não for configurado explicitamente, a aplicação também recorrerá ao arquivo de segredo padrão em `storage`.
|
||||
- Em contêineres efêmeros ou implantações com múltiplos nós, depender de arquivos de chave locais gerados automaticamente pode fazer com que os tokens se tornem inválidos após um reinício, ou que dados históricos criptografados não possam mais ser descriptografados.
|
||||
|
||||
:::info{title=Dica}
|
||||
`APP_AES_SECRET_KEY` deve ser uma chave AES-256 de 32 bytes, representada por 64 caracteres hexadecimais.
|
||||
|
||||
Em ambientes de nuvem, recomenda-se gerenciar esses valores centralmente por meio de serviços como Secrets Manager, SSM Parameter Store, Kubernetes Secret ou um arquivo de chave montado em modo somente leitura.
|
||||
:::
|
||||
|
||||
### Modo Multi-core
|
||||
|
||||
Quando o aplicativo é executado em um nó multi-core, você pode habilitar o modo multi-core do nó:
|
||||
@@ -160,4 +215,4 @@ Atualmente, cada plugin utiliza suas próprias variáveis de ambiente relacionad
|
||||
|
||||
Se você usa Kubernetes para gerenciar o cluster, pode configurar as variáveis de ambiente acima em um ConfigMap ou Secret. Para mais conteúdo relacionado, consulte [Implantação Kubernetes](./kubernetes).
|
||||
|
||||
Após a conclusão de todas as preparações acima, você pode prosseguir para as [Operações](./operations) para continuar gerenciando as instâncias do aplicativo.
|
||||
Após a conclusão de todas as preparações acima, você pode prosseguir para as [Operações](./operations) para continuar gerenciando as instâncias do aplicativo.
|
||||
|
||||
@@ -11,6 +11,10 @@ keywords: "кластерный режим,несколько экземпляр
|
||||
|
||||
Начиная с версии v1.6.0, NocoBase поддерживает запуск приложений в кластерном режиме. При работе приложения в кластерном режиме вы можете повысить его производительность при обработке параллельных запросов, используя несколько экземпляров и многоядерный режим.
|
||||
|
||||
На основе кластерного режима можно реализовать высокую доступность на уровне приложения: балансировщик нагрузки распределяет трафик между несколькими экземплярами NocoBase внутри одного кластера, поэтому при сбое, перезапуске или выпуске новой версии одного экземпляра остальные экземпляры продолжают обслуживать запросы. На практике один кластер обычно следует разворачивать в пределах одной низколатентной сетевой среды.
|
||||
|
||||
Важно отметить, что кластерный режим NocoBase решает задачи горизонтального масштабирования и высокой доступности экземпляров приложения именно на уровне приложения. Если вам требуется warm standby или аварийное восстановление между зонами доступности или регионами, обычно следует развернуть несколько независимых кластеров, а команда эксплуатации должна самостоятельно отвечать за стратегию репликации и переключения базы данных, общего хранилища и другой инфраструктуры.
|
||||
|
||||
## Архитектура системы
|
||||
|
||||

|
||||
@@ -31,4 +35,4 @@ keywords: "кластерный режим,несколько экземпляр
|
||||
- [Эксплуатация](./operations)
|
||||
- Расширенные возможности
|
||||
- [Разделение сервисов](./services-splitting)
|
||||
- [Справочник разработчика](./development)
|
||||
- [Справочник разработчика](./development)
|
||||
|
||||
@@ -25,12 +25,14 @@ keywords: "подготовка кластера,коммерческая лиц
|
||||
|
||||
## Системные компоненты
|
||||
|
||||
Другие системные компоненты, помимо самого экземпляра приложения, могут быть выбраны специалистами по эксплуатации в соответствии с потребностями вашей команды.
|
||||
Помимо самих экземпляров приложения, развертывание в кластере также требует таких системных компонентов, как база данных, промежуточное ПО, общее хранилище и балансировка нагрузки. Каждая команда может выбрать конкретную реализацию этих компонентов в соответствии со своей собственной эксплуатационной моделью.
|
||||
|
||||
### База данных
|
||||
|
||||
Поскольку текущий кластерный режим ориентирован только на экземпляры приложений, база данных временно поддерживает только один узел. Если у вас есть архитектура базы данных типа «мастер-подчиненный» (master-slave) или аналогичная, вам потребуется реализовать ее самостоятельно с помощью промежуточного ПО, обеспечив при этом прозрачность для приложения NocoBase.
|
||||
|
||||
Если вам требуется warm standby или аварийное восстановление между зонами доступности или регионами, стратегия синхронизации и переключения базы данных должна быть спроектирована и реализована вашей командой эксплуатации.
|
||||
|
||||
### Промежуточное ПО
|
||||
|
||||
Кластерный режим NocoBase требует использования промежуточного ПО для обеспечения связи и координации между кластерами, включая:
|
||||
@@ -49,10 +51,37 @@ keywords: "подготовка кластера,коммерческая лиц
|
||||
|
||||
### Общее хранилище
|
||||
|
||||
NocoBase использует каталог `storage` для хранения системных файлов. В многоузловом режиме вам следует монтировать облачный диск (или NFS) для обеспечения общего доступа между несколькими узлами. В противном случае локальное хранилище не будет автоматически синхронизироваться, и приложение не сможет работать корректно.
|
||||
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`, а не как высокопроизводительный файловый сервис.
|
||||
- Такие операции, как установка и обновление плагинов, резервное копирование, восстановление и миграция, выполнять только после сокращения кластера до одного узла; после завершения кластер можно снова масштабировать.
|
||||
|
||||
### Балансировка нагрузки
|
||||
|
||||
Кластерный режим требует использования балансировщика нагрузки для распределения запросов, а также для проверки работоспособности и обеспечения отказоустойчивости экземпляров приложений. Выбор и настройка этой части осуществляется в соответствии с эксплуатационными потребностями вашей команды.
|
||||
@@ -61,7 +90,6 @@ NocoBase использует каталог `storage` для хранения
|
||||
|
||||
```
|
||||
upstream myapp {
|
||||
# ip_hash; # Может использоваться для сохранения сессий. При включении запросы от одного и того же клиента всегда отправляются на один и тот же бэкенд-сервер.
|
||||
server 172.31.0.1:13000; # Внутренний узел 1
|
||||
server 172.31.0.2:13000; # Внутренний узел 2
|
||||
server 172.31.0.3:13000; # Внутренний узел 3
|
||||
@@ -82,10 +110,37 @@ server {
|
||||
|
||||
Для промежуточного ПО балансировки нагрузки, предоставляемого другими облачными провайдерами, пожалуйста, обратитесь к документации по конфигурации, предоставленной конкретным провайдером.
|
||||
|
||||
Для развертываний с высокой доступностью рекомендуется:
|
||||
|
||||
- Запускать как минимум 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 или файл ключа, смонтированный только для чтения.
|
||||
:::
|
||||
|
||||
### Многоядерный режим
|
||||
|
||||
Когда приложение работает на многоядерном узле, вы можете включить многоядерный режим для этого узла:
|
||||
@@ -159,4 +214,4 @@ REDIS_URL=redis://localhost:6379/4
|
||||
|
||||
Если вы используете Kubernetes для управления кластером, вы можете настроить вышеуказанные переменные окружения в ConfigMap или Secret. Дополнительную информацию можно найти в разделе [Развертывание в Kubernetes](./kubernetes).
|
||||
|
||||
После завершения всех вышеуказанных подготовительных работ вы можете перейти к [процессу эксплуатации](./operations), чтобы продолжить управление экземплярами приложения.
|
||||
После завершения всех вышеуказанных подготовительных работ вы можете перейти к [процессу эксплуатации](./operations), чтобы продолжить управление экземплярами приложения.
|
||||
|
||||
@@ -449,6 +449,9 @@ TableColumnModel.registerFlow({
|
||||
quickEdit: {
|
||||
title: tExpr('Enable quick edit'),
|
||||
uiMode: { type: 'switch', key: 'editable' },
|
||||
hideInSettings(ctx) {
|
||||
return !!ctx.model.associationPathName;
|
||||
},
|
||||
defaultParams(ctx) {
|
||||
if (ctx.model.collectionField.readonly || ctx.model.associationPathName) {
|
||||
return {
|
||||
@@ -460,7 +463,7 @@ TableColumnModel.registerFlow({
|
||||
};
|
||||
},
|
||||
handler(ctx, params) {
|
||||
ctx.model.setProps('editable', params.editable);
|
||||
ctx.model.setProps('editable', ctx.model.associationPathName ? false : params.editable);
|
||||
},
|
||||
},
|
||||
model: {
|
||||
|
||||
+36
@@ -12,6 +12,42 @@ import { describe, expect, it, vi } from 'vitest';
|
||||
import { TableColumnModel } from '../TableColumnModel';
|
||||
|
||||
describe('TableColumnModel sorter settings', () => {
|
||||
it('hides quick edit setting for relation path columns added from association groups', async () => {
|
||||
const engine = new FlowEngine();
|
||||
const model = new TableColumnModel({ uid: 'table-column-relation-path-quick-edit', flowEngine: engine } as any);
|
||||
const quickEditStep = model.getFlow('tableColumnSettings')?.steps?.quickEdit as any;
|
||||
|
||||
const hidden = await quickEditStep.hideInSettings({
|
||||
model: {
|
||||
associationPathName: 'department',
|
||||
},
|
||||
});
|
||||
|
||||
expect(hidden).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps quick edit disabled for relation path columns even when params enable it', () => {
|
||||
const engine = new FlowEngine();
|
||||
const model = new TableColumnModel({
|
||||
uid: 'table-column-relation-path-disable-quick-edit',
|
||||
flowEngine: engine,
|
||||
} as any);
|
||||
const quickEditStep = model.getFlow('tableColumnSettings')?.steps?.quickEdit as any;
|
||||
const setProps = vi.fn();
|
||||
|
||||
quickEditStep.handler(
|
||||
{
|
||||
model: {
|
||||
associationPathName: 'department',
|
||||
setProps,
|
||||
},
|
||||
},
|
||||
{ editable: true },
|
||||
);
|
||||
|
||||
expect(setProps).toHaveBeenCalledWith('editable', false);
|
||||
});
|
||||
|
||||
it('hides sortable setting for association fields', async () => {
|
||||
const engine = new FlowEngine();
|
||||
const model = new TableColumnModel({ uid: 'table-column-association-sorter', flowEngine: engine } as any);
|
||||
|
||||
@@ -48,6 +48,13 @@ export class DisplayEnumFieldModel extends ClickableFieldModel {
|
||||
return value === null || value === undefined || value === '';
|
||||
}
|
||||
|
||||
private isEmptyEnumValue(value: any) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length === 0;
|
||||
}
|
||||
return this.isEmpty(value);
|
||||
}
|
||||
|
||||
public renderComponent(value) {
|
||||
const { options = [], dataSource } = this.props;
|
||||
const currentOptions = getCurrentOptions(value, dataSource || options, fieldNames);
|
||||
@@ -61,6 +68,43 @@ export class DisplayEnumFieldModel extends ClickableFieldModel {
|
||||
</Tag>
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep array values for multipleSelect/checkboxGroup.
|
||||
* ClickableFieldModel will normalize arrays to joined strings, which breaks option label mapping.
|
||||
*/
|
||||
renderInDisplayStyle(value, record?, isToMany?, wrap?) {
|
||||
const { clickToOpen = false, ...restProps } = this.props;
|
||||
void wrap;
|
||||
|
||||
const result = this.renderComponent(value);
|
||||
const display = record ? (this.isEmptyEnumValue(value) ? 'N/A' : result) : result;
|
||||
|
||||
const commonStyle = {
|
||||
cursor: clickToOpen ? 'pointer' : 'default',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
display: isToMany && 'inline-block',
|
||||
};
|
||||
|
||||
const handleClick = (e) => {
|
||||
clickToOpen && this.onClick(e, record);
|
||||
};
|
||||
|
||||
if (clickToOpen) {
|
||||
return (
|
||||
<a {...restProps} style={commonStyle} onClick={handleClick}>
|
||||
{display}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span {...restProps} style={commonStyle} className={restProps.className}>
|
||||
{display}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
DisplayEnumFieldModel.define({
|
||||
label: tExpr('Select'),
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { FlowEngine } from '@nocobase/flow-engine';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { DisplayEnumFieldModel } from '../DisplayEnumFieldModel';
|
||||
|
||||
describe('DisplayEnumFieldModel', () => {
|
||||
it('renders labels for multiple values (multipleSelect/checkboxGroup)', () => {
|
||||
const engine = new FlowEngine();
|
||||
engine.registerModels({ DisplayEnumFieldModel });
|
||||
|
||||
const model = engine.createModel<DisplayEnumFieldModel>({
|
||||
use: DisplayEnumFieldModel,
|
||||
uid: 'display-enum-multiple-values',
|
||||
});
|
||||
|
||||
model.setProps({
|
||||
value: ['a', 'b'],
|
||||
options: [
|
||||
{ label: 'Option A', value: 'a' },
|
||||
{ label: 'Option B', value: 'b' },
|
||||
],
|
||||
});
|
||||
|
||||
render(model.render());
|
||||
|
||||
expect(screen.getByText('Option A')).toBeInTheDocument();
|
||||
expect(screen.getByText('Option B')).toBeInTheDocument();
|
||||
expect(screen.queryByText('a, b')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -37,16 +37,22 @@ import { transformMultiColumnToSingleColumn } from '@nocobase/utils/client';
|
||||
export interface FormProps extends IFormLayoutProps {
|
||||
form?: FormilyForm;
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* Override the internally calculated scroll container height.
|
||||
* Used by blocks that compose additional headers/footers outside FormV2.
|
||||
*/
|
||||
height?: number;
|
||||
}
|
||||
|
||||
const FormComponent: React.FC<FormProps> = (props) => {
|
||||
const { form, children, ...others } = props;
|
||||
const { form, children, height: heightProp, ...others } = props;
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const cardItemSchema = getCardItemSchema?.(fieldSchema);
|
||||
// TODO: component 里 useField 会与当前 field 存在偏差
|
||||
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
||||
const height = useFormBlockHeight();
|
||||
const computedHeight = useFormBlockHeight();
|
||||
const height = Number.isFinite(heightProp as any) ? heightProp : computedHeight;
|
||||
const { token } = theme.useToken();
|
||||
const {
|
||||
layout = 'vertical',
|
||||
@@ -115,7 +121,7 @@ const FormComponent: React.FC<FormProps> = (props) => {
|
||||
const Def = (props: any) => props.children;
|
||||
|
||||
const FormDecorator: React.FC<FormProps> = (props) => {
|
||||
const { form, children, disabled, ...others } = props;
|
||||
const { form, children, disabled, height: _heightProp, ...others } = props;
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
// TODO: component 里 useField 会与当前 field 存在偏差
|
||||
|
||||
+20
-7
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
// refer to packages/core/client/src/schema-component/antd/form-v2/hook.ts
|
||||
import { useDataBlockHeight, useBlockHeightProps, useFormDataTemplates, useDesignable } from '@nocobase/client';
|
||||
import { theme } from 'antd';
|
||||
@@ -7,22 +16,26 @@ export default function useHeight() {
|
||||
const { token } = theme.useToken();
|
||||
const { designable } = useDesignable();
|
||||
const { heightProps } = useBlockHeightProps() || {};
|
||||
const { title } = heightProps || {};
|
||||
const { title, titleHeight } = heightProps || {};
|
||||
const { display, enabled } = useFormDataTemplates();
|
||||
|
||||
if (typeof height !== 'number') return;
|
||||
|
||||
const isFormBlock = true;
|
||||
const actionBarHeight = designable ? token.controlHeight + (isFormBlock ? 1 : 2) * token.marginLG : token.marginLG;
|
||||
const blockTitleHeaderHeight = title ? token.fontSizeLG * token.lineHeightLG + token.padding * 2 - 1 : 0;
|
||||
const actionBarHeight = designable
|
||||
? token.controlHeight + (isFormBlock ? 1 : 2) * token.marginLG
|
||||
: token.marginLG + token.controlHeight;
|
||||
const blockTitleHeaderHeight = title ? titleHeight || 0 : 0;
|
||||
const paginationHeight = 0;
|
||||
const dataTemplateHeight = display && enabled ? token.controlHeight + 2 * token.padding + token.margin : 0;
|
||||
const stepHeight = 56;
|
||||
return (
|
||||
const stepHeight = 76;
|
||||
const nextHeight =
|
||||
height -
|
||||
actionBarHeight -
|
||||
token.paddingLG -
|
||||
blockTitleHeaderHeight -
|
||||
paginationHeight -
|
||||
dataTemplateHeight -
|
||||
stepHeight
|
||||
);
|
||||
stepHeight;
|
||||
return Number.isFinite(nextHeight) ? nextHeight : undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user