From 06c8a3db2b6001351a2853c091b870f78d0be940 Mon Sep 17 00:00:00 2001 From: chengcheng Date: Thu, 16 Jul 2026 19:06:29 +0800 Subject: [PATCH] =?UTF-8?q?docs(deploy):=20=E6=8C=89=E5=AE=98=E6=96=B9?= =?UTF-8?q?=E4=BE=9D=E6=8D=AE=E6=A0=A1=E5=87=86=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a7ea76d..9f48f39 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,9 @@ kubectl get storageclass #### 生产初始规格与容量基线 -客户尚未提供业务容量数据时,可先按下表准备生产环境。表中的 CPU、内存和磁盘均为**单个数据节点**的规格,标注“当前模板”的项目与仓库 YAML 一致;标注“规划参考”的外部依赖需根据实际业务量和压测结果调整。本表用于资源准备和首次上线,不代表固定性能或容量承诺。 +客户尚未提供业务容量数据时,可先按下表准备生产环境。表中的 CPU、内存和磁盘均为**单个数据节点**的规格,标注“当前模板”的项目与仓库 YAML 一致;标注“官方容量参考”的项目引用官方规格指南;标注“项目初始值”的项目是用于首次部署和压测的起点,不是官方最低配置或吞吐量承诺。 + +数据库访问量应使用峰值数据库读写操作数、事务数和活跃数据库会话衡量,不能直接用日活、PV 或在线用户数代替。同一个 API 请求可能不访问数据库,也可能触发多次查询、写入或后台任务。 EasyAI 应用 Pod 当前资源规格如下,CPU 和内存均为单个 Pod 的配置: @@ -90,34 +92,135 @@ EasyAI 应用 Pod 当前资源规格如下,CPU 和内存均为单个 Pod 的 | 依赖 | 建议生产拓扑 | 单节点初始规格 | 初始存储容量 | 备注 | | --- | --- | --- | --- | --- | -| MongoDB | 云服务高可用版,或 3 个数据节点的副本集 | `4 vCPU / 16Gi` | 每节点 `200Gi` SSD | 规划参考;数据盘不包含备份和快照空间 | +| MongoDB | 云服务高可用版,或 3 个数据节点的副本集 | Atlas `M30` 参考值为 `2 vCPU / 8GB`;自建环境以压测为准 | 无存量数据时每节点可从 `50Gi` SSD 开始压测;已有数据按下方公式计算 | `M30` 的 `3000/s` 和 `20–50GB` 是 Atlas 近似集群负载,不是自建单节点性能承诺 | | Redis | 云服务高可用版,或主节点 + 2 个副本并配套 Sentinel | `2 vCPU / 4Gi` | 每节点 `20Gi` SSD,建议 `maxmemory` 初始设为 `2Gi` | 规划参考;必须支持多个逻辑 DB 和 `SELECT`,当前不支持 Redis Cluster 模式 | | RabbitMQ | 3 节点集群,持久化业务队列使用 quorum queue | 请求 `1 vCPU / 2Gi`,上限 `2 vCPU / 2Gi` | 每节点 `50Gi` RWO SSD,总计 `150Gi` | 当前自建模板实际值;高吞吐或大消息场景需压测后增加内存和磁盘 | -| PostgreSQL + pgvector | 云服务高可用版,或 1 主 1 备 | `4 vCPU / 16Gi` | 每节点 `200Gi` SSD | 规划参考;可在同一实例创建 `agent_governance` 和 `easyai_memory` 两个数据库 | +| PostgreSQL + pgvector | 云服务高可用版,或主库 + 备库并配置经过验证的自动故障切换、隔离机制和统一访问端点 | 按实际 SQL、并发客户端和向量检索压测确定 | 无存量数据时每节点可从 `50Gi` SSD 开始压测;已有数据按下方公式计算 | PostgreSQL 官方没有统一的 TPS 与硬件换算;本地 `1 CPU / 1Gi` 仅为功能验证上限,不是生产基线 | | RWX 共享存储 | 支持高可用和在线扩容的 RWX 存储 | 由存储服务决定 | 初始总容量 `100Gi` | 当前生产 PVC 实际值;不包含独立备份空间 | | OSS/S3 对象存储 | 云厂商托管对象存储 | 由对象存储服务决定 | 按量使用,无需预分配固定容量 | 可选;建议配置生命周期和历史文件清理策略 | -最终容量应根据客户业务数据计算: +##### MongoDB 规格计算依据 + +[MongoDB Atlas Cluster Size Guide](https://www.mongodb.com/docs/atlas/architecture/current/hierarchy/#atlas-cluster-size-guide) 明确说明规格表仅用于近似起点,最终规格需要根据资源需求、性能目标、负载特征和增长持续迭代。官方给出的初步估算公式为: ```text -初始可用容量 >=(现有数据量 + 日增量 × 在线保留天数)× 1.5 +预计数据存储 = 原始数据量 × 50% +预计 RAM = 原始数据量 × 10% +预计 CPU 核数 = 峰值数据库读写操作数/秒 ÷ 4000 +预计存储 IOPS = 峰值数据库读写操作数/秒 ``` -其中 `1.5` 用于预留索引、临时文件、数据增长和运维空间。数据盘使用率达到 `70%` 时告警,达到 `80%` 前完成扩容;备份、快照和跨区域副本应单独计算,不占用上表的数据盘容量。 +Atlas 官方档位如下。CPU、内存和 IOPS 是 Atlas 数据节点的规格,典型数据量和峰值读写操作数是近似集群负载;自建 MongoDB 的云盘、CPU 型号和文件系统不同,不能把 Atlas 数值当作自建环境的固定性能承诺。 + +| Atlas 参考档 | CPU | 内存 | 默认 IOPS | 典型数据量 | 峰值读写操作数 | 官方用途 | +| --- | ---: | ---: | ---: | ---: | ---: | --- | +| `M10` | `2` | `2GB` | `1000` | `1–10GB` | `200/s` | 开发/测试 | +| `M30` | `2` | `8GB` | `3000` | `20–50GB` | `3000/s` | 生产 | +| `M50` | `16` | `32GB` | `3000` | `360–420GB` | `11000/s` | 生产 | +| `M80` | `32` | `128GB` | `3000` | `1200–1750GB` | `39000/s` | 生产 | + +使用 MongoDB Atlas 时,客户未提供容量和压测数据可先选择 `M30` 作为生产准备参考,而不是原来的 `4 vCPU / 16Gi` 自建节点规格。自建环境可以使用 `2 vCPU / 8Gi` 作为首轮压测候选,但不能直接继承 Atlas 的吞吐量结论。如果实测负载低于 `M10` 参考范围,可在客户接受性能验证结果的前提下降配;高于 `M30` 范围时,应按数据量和峰值操作数选择更高档位并重新压测。 + +MongoDB 的实际峰值操作数应通过 [`mongostat`](https://www.mongodb.com/docs/database-tools/mongostat/) 或 [`serverStatus.opcounters`](https://www.mongodb.com/docs/manual/reference/command/serverstatus/#mongodb-serverstatus-serverstatus.opcounters) 的时间差值测量,现有物理数据和索引大小通过 [`dbStats`](https://www.mongodb.com/docs/manual/reference/command/dbstats/) 测量。项目数据盘计算公式为: + +```text +MongoDB 单节点数据盘 +>=(压缩后数据 + 索引 + oplog + 在线保留期增长量)÷ 0.7 +``` + +除以 `0.7` 是为了符合本项目“使用率达到 `70%` 告警”的运维策略,不是 MongoDB 官方固定系数。3 个数据节点用于副本集高可用,每个节点都需要容纳完整数据副本;[MongoDB 官方推荐的最小副本集配置](https://www.mongodb.com/docs/manual/core/replica-set-members/)是 3 个数据承载节点。 + +##### PostgreSQL 与 pgvector 规格计算依据 + +PostgreSQL 官方没有提供“多少 QPS/TPS 对应多少 CPU 和内存”的通用硬件表。查询复杂度、索引命中率、并发事务、向量维度、HNSW/IVFFlat 选择、召回率目标和存储延迟都会显著改变结果。当前仓库只有本地功能验证数据,没有可支撑固定生产 CPU/内存数字的项目压测结果,因此生产规格必须通过实际负载确定。 + +自建高可用不能只写成“1 主 1 备”。还必须使用经过验证的高可用管理方案完成故障检测、自动切换、主库隔离或 fencing、客户端访问端点切换以及故障域隔离;所选方案需要仲裁或 witness 时还必须部署对应组件,并完成故障演练。 + +内存规划应遵循 [PostgreSQL 18 Resource Consumption](https://www.postgresql.org/docs/18/runtime-config-resource.html): + +- 专用数据库服务器的 `shared_buffers` 可从系统内存的 `25%` 起步;官方说明超过 `40%` 通常不会比更小的值更好,因为 PostgreSQL 同时依赖操作系统文件缓存。 +- `work_mem` 是每个排序或哈希操作的基础上限,一个复杂查询可能同时使用多份 `work_mem`,多个会话还会并发叠加;哈希操作的内存上限还要乘以 `hash_mem_multiplier`,默认值为 `2.0`。 +- `maintenance_work_mem` 可用于 `VACUUM` 和建索引,但 autovacuum 最多可能按 worker 数量重复分配相关内存。 +- `max_connections` 默认通常为 `100`,提高它会增加共享内存等资源分配;连接上限不能当作数据库吞吐量目标。 + +规划并发内存时至少要检查以下上界,而不能只看 `shared_buffers`: + +```text +排序瞬时内存 +≈ 活跃排序操作实例数 × work_mem + +哈希瞬时内存 +≈ 活跃哈希操作实例数 × work_mem × hash_mem_multiplier + +HNSW 迭代扫描内存 +≈ 并发 HNSW 扫描执行实例数 × work_mem × hnsw.scan_mem_multiplier + +数据库节点内存 +> shared_buffers + + 排序瞬时内存 + + 哈希瞬时内存 + + HNSW 迭代扫描内存 + + autovacuum/维护任务内存 + + 会话本地内存、连接进程、操作系统和文件缓存预留 +``` + +[pgvector `0.8.2` 官方说明](https://github.com/pgvector/pgvector/blob/v0.8.2/README.md#index-build-time)指出,HNSW 的查询性能通常优于 IVFFlat,但建索引更慢且使用更多内存;当 HNSW 图可以放入 `maintenance_work_mem` 时建索引明显更快,同时明确警告不能把该参数设置到耗尽服务器内存。`hnsw.ef_search`、`hnsw.scan_mem_multiplier` 和 IVFFlat `probes` 也会在召回率、速度和内存之间产生取舍。上式中的执行实例数必须把 leader 和参与查询的并行 worker 分别计算。存在较大向量索引或在线建索引需求时,应根据实际 HNSW 图大小临时提高维护窗口资源并重新压测,不能预先写死 CPU 和内存规格。 + +PostgreSQL 单节点数据盘按实际数据库大小计算: + +```text +PostgreSQL 单节点数据盘 +>=(pg_database_size('agent_governance') + + pg_database_size('easyai_memory') + + 其他数据库和集群级空间 + + WAL 预留 + + 临时文件预留 + + 最大计划索引重建、REINDEX 或表重写工作空间 + + 在线保留期增长量)÷ 0.7 +``` + +[`pg_database_size`](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE) 包含数据库中的表、索引和 TOAST 数据;使用额外 tablespace 时还要分别确认其存储卷容量。WAL 位于集群级目录,需要单独预留。[PostgreSQL WAL 官方说明](https://www.postgresql.org/docs/18/wal-configuration.html)指出 `max_wal_size` 是软限制,在高负载、归档失败、较大的 `wal_keep_size` 或复制槽滞后时可能被超过,因此不能只按 `max_wal_size` 配置磁盘。主库和物理备库都需要容纳完整数据副本,备份和归档空间另行计算。 + +PostgreSQL 最终规格必须使用 [PostgreSQL `pgbench`](https://www.postgresql.org/docs/18/pgbench.html) 的自定义事务脚本模拟 EasyAI 实际 SQL: + +1. 使用 `-f` 编写覆盖 Agent 治理写入、记忆写入、普通查询和向量检索的混合事务脚本; +2. `-c` 表示并发客户端连接数,不等于生产环境的活跃会话数或请求到达率;需要结合实际连接池、思考时间,并在模拟固定到达率时使用 `-R`,同时通过 `pg_stat_activity` 验证数据库内实际活跃会话; +3. 使用 `-T` 运行至少数分钟并重复多轮; +4. 记录 TPS、事务延迟、失败事务和超过延迟限制的事务,不能使用默认 TPC-B-like 脚本结果直接代表 EasyAI; +5. 同时检查 `pg_stat_database` 的连接数、事务提交/回滚、磁盘块读取、临时文件、临时字节数和死锁; +6. 启用 [`pg_stat_statements`](https://www.postgresql.org/docs/18/pgstatstatements.html) 后,检查实际 SQL 的调用次数、平均/最大执行时间、缓存命中、临时块、WAL 量和 I/O 时间;只有启用 `track_io_timing` 后 I/O 时间字段才有有效值,启用前应评估所在平台的计时开销; +7. 选择满足客户峰值负载和延迟目标的最小规格,并在向量数量、维度、索引类型或召回率目标改变后重新压测。 + +##### 容量信息与扩容规则 上线前请客户补充以下信息,以便把初始参考规格调整为最终规格: -- 峰值并发用户数和同时运行的任务数; +- API 峰值 QPS、MongoDB 峰值读写操作数/秒和 PostgreSQL 峰值 TPS; +- PostgreSQL 峰值活跃数据库会话数、目标事务延迟和主要 SQL 类型; - 每日任务量、峰值队列积压量及单条消息大小; -- 现有数据库大小、每日数据增量和在线保留天数; +- MongoDB 原始/压缩数据、索引和 oplog 大小; +- PostgreSQL 两个数据库的 `pg_database_size`、WAL 峰值和临时文件峰值; +- 向量条数、向量维度、索引类型、目标召回率和是否需要在线建索引; +- 每日数据库增量和在线保留天数; - 每日上传文件量、平均文件大小和文件保留周期; - 备份周期、保留份数以及 RPO/RTO 要求。 -本地验证环境中的依赖为单节点和临时 `emptyDir` 存储,只用于功能验证,不能作为生产规格。MongoDB、Redis 和 PostgreSQL 的资源规划可参考官方生产说明: +所有数据盘在使用率达到 `70%` 时告警,达到 `80%` 前完成扩容。备份、快照、WAL 归档和跨区域副本空间单独计算。当前本地验证模板中 MongoDB 上限为 `1 CPU / 2500Mi`,PostgreSQL 上限为 `1 CPU / 1Gi`,且均使用单节点 `emptyDir`;这些数值只证明低负载功能验证可以运行,不能作为生产容量依据。 +资源规划参考: + +- [MongoDB Atlas Cluster Size Guide](https://www.mongodb.com/docs/atlas/architecture/current/hierarchy/#atlas-cluster-size-guide) - [MongoDB Production Notes](https://www.mongodb.com/docs/manual/administration/production-notes/) +- [MongoDB Replica Set Members](https://www.mongodb.com/docs/manual/core/replica-set-members/) +- [MongoDB WiredTiger Memory Use](https://www.mongodb.com/docs/manual/core/wiredtiger/#memory-use) - [Redis Administration](https://redis.io/docs/latest/operate/oss_and_stack/management/admin/) -- [PostgreSQL Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html) +- [PostgreSQL 18 Resource Consumption](https://www.postgresql.org/docs/18/runtime-config-resource.html) +- [PostgreSQL 18 Connections](https://www.postgresql.org/docs/18/runtime-config-connection.html) +- [PostgreSQL 18 pgbench](https://www.postgresql.org/docs/18/pgbench.html) +- [PostgreSQL 18 Monitoring Statistics](https://www.postgresql.org/docs/18/monitoring-stats.html) +- [PostgreSQL 18 Disk Usage](https://www.postgresql.org/docs/18/diskusage.html) +- [PostgreSQL 18 WAL Configuration](https://www.postgresql.org/docs/18/wal-configuration.html) +- [pgvector 0.8.2](https://github.com/pgvector/pgvector/blob/v0.8.2/README.md) - [RabbitMQ Quorum Queues](https://www.rabbitmq.com/docs/quorum-queues) #### Redis 逻辑 DB 配置