# Redis 对接协议(供外部项目 AI 生成代码使用) 本文档定义"外部项目 ↔ BLS Project Console"之间通过 Redis 交互的 **Key 命名、数据类型、写入方式、读取方式与数据格式**。 注:本仓库对外暴露的 Redis 连接信息如下(供对方直接连接以写入心跳/日志): - 地址:`10.8.8.109` - 端口:默认 `6379` - 密码:无(空) - 数据库:固定 `15` 示例(环境变量): ``` REDIS_HOST=10.8.8.109 REDIS_PORT=6379 REDIS_PASSWORD= REDIS_DB=15 ``` 示例(redis-cli): ``` redis-cli -h 10.8.8.109 -p 6379 -n 15 ``` > 约束:每个需要关联本控制台的外部项目,必须在同一个 Redis(DB15)中: > - 更新 `项目心跳`(项目列表 + 心跳信息) > - 追加 `${projectName}_项目控制台`(日志队列) > - 命令下发为 HTTP API 调用(不通过 Redis 下发命令) ## 1. 命名约定 令: - `projectName`:外部项目名称(建议只用字母数字下划线 `A-Za-z0-9_`;如使用中文也可,但需保证统一且 UTF-8)。 固定后缀: - 控制台:`${projectName}_项目控制台` 示例(projectName = `订单系统`): - `订单系统_项目控制台` ## 2. 外部项目需要写入的 2 个 Key 说明:当前控制台左侧“项目选择列表”只读取 `项目心跳`(LIST)。因此外部项目必须维护该 Key,否则项目不会出现在列表中。 ### 2.1 `项目心跳` - Redis 数据类型:**LIST** - 写入方式(推荐 FIFO):`RPUSH 项目心跳 ` - value:每个列表元素为“项目心跳记录”的 JSON 字符串 示例(与当前代码读取一致;下面示例表示“逻辑结构”): ```json [ { "projectName": "BLS主机心跳日志", "apiBaseUrl": "http://127.0.0.1:3000", "lastActiveAt": 1768566165572 } ] ``` 示例(Redis 写入命令): ``` RPUSH 项目心跳 "{\"projectName\":\"BLS主机心跳日志\",\"apiBaseUrl\":\"http://127.0.0.1:3000\",\"lastActiveAt\":1768566165572}" ``` 字段说明(每条心跳记录): - `projectName`:项目名称(用于拼接日志 Key:`${projectName}_项目控制台`) - `apiBaseUrl`:目标项目对外提供的 API 地址(基地址,后端将基于它拼接 `apiName`) - `lastActiveAt`:活跃时间戳(毫秒)。建议每 **3 秒**刷新一次。 在线/离线判定(BLS Project Console 使用): - 若 `now - lastActiveAt > 10_000ms`,则认为该应用 **离线** - 否则认为 **在线** 建议: - `lastActiveAt` 使用 `Date.now()` 生成(毫秒) - 建议对 `项目心跳` 做长度控制(可选):例如每次写入后执行 `LTRIM 项目心跳 -2000 -1` 保留最近 2000 条 去重提示: - `项目心跳` 为 LIST 时,外部项目周期性 `RPUSH` 会产生多条重复记录 - BLS Project Console 后端会按 `projectName` 去重,保留 `lastActiveAt` 最新的一条作为项目状态 ### 2.2 `${projectName}_项目控制台` - Redis 数据类型:**LIST**(作为项目向控制台追加的"消息队列/日志队列") - 写入方式(推荐 FIFO):`RPUSH ${projectName}_项目控制台 ` value(推荐格式):一条 JSON 字符串,表示"错误/调试信息"或日志记录。 推荐 JSON Schema(字段尽量保持稳定,便于控制台解析): ```json { "timestamp": "2026-01-12T12:34:56.789Z", "level": "info", "message": "连接成功", "metadata": { "module": "redis", "host": "127.0.0.1" } } ``` 字段说明: - `timestamp`:ISO-8601 时间字符串 - `level`:建议取值 `info|warn|error|debug`(小写) - `message`:日志文本 - `metadata`:可选对象(附加信息) ## 3. 项目列表管理(重要) ### 3.1 迁移机制(仅用于旧数据导入) BLS Project Console 支持从旧格式自动迁移到新格式: - **旧格式**:每个项目独立的心跳键 `${projectName}_项目心跳` - **新格式**:统一的项目列表键 `项目心跳`(LIST 类型,每个元素为 JSON 字符串) 迁移过程: 1. 扫描所有 `${projectName}_项目心跳` 键 2. 提取 `apiBaseUrl` 和 `lastActiveAt` 字段 3. 写入到 `项目心跳`(LIST) 4. 可选:删除旧键 重要说明(与当前代码实现一致): - 迁移不会自动后台执行,需要通过接口触发:`POST /api/projects/migrate` - 迁移的目的只是“从历史 `${projectName}_项目心跳` 导入一次,生成 `项目心跳` 列表” - 迁移完成后,如果外部项目仍然只更新旧 Key,则 `项目心跳` 不会自动跟随更新;要想实时更新,外部项目必须直接更新 `项目心跳` ### 3.2 新格式项目列表结构 `项目心跳` 为 LIST,列表元素为 JSON 字符串;其“逻辑结构”如下: ```json [ { "projectName": "订单系统", "apiBaseUrl": "http://127.0.0.1:4001", "lastActiveAt": 1760000000000 }, { "projectName": "用户服务", "apiBaseUrl": "http://127.0.0.1:4002", "lastActiveAt": 1760000000001 } ] ``` ### 3.3 外部项目对接建议 外部项目应当: 1. 定期写入 `项目心跳`(RPUSH 自己的心跳记录;允许产生多条记录,由控制台按 projectName 去重) 2. 追加 `${projectName}_项目控制台` 日志 ## 4. 命令下发方式(HTTP API 控制) 控制台不再通过 Redis 写入控制指令队列;改为由 BLS Project Console 后端根据目标项目心跳里的 `apiBaseUrl` 直接调用目标项目 HTTP API。 ### 4.1 控制台输入格式 一行文本按空格拆分: - 第一个 token:`apiName`(接口名/路径片段) - 剩余 token:参数列表(字符串数组) 示例: - `reload` - `reload force` - `user/refreshCache tenantA` ### 4.2 目标项目需要提供的 API 后端默认使用 `POST` 调用: - `POST {apiBaseUrl}/{apiName}` 请求体(JSON)示例: ```json { "commandId": "cmd-1700000000000-abc123", "timestamp": "2026-01-13T00:00:00.000Z", "source": "BLS Project Console", "apiName": "reload", "args": ["force"], "argsText": "force" } ``` 字段说明: - `commandId`:唯一命令标识符 - `timestamp`:命令发送时间(ISO-8601 格式) - `source`:命令来源标识 - `apiName`:API 接口名 - `args`:参数数组 - `argsText`:参数文本(空格连接) 返回建议: - 2xx 表示成功 - 非 2xx 表示失败(控制台会展示 upstreamStatus 与部分返回内容) ### 4.3 在线/离线判定 发送命令前,系统会检查项目在线状态: - 从 `项目心跳` 列表读取 `lastActiveAt` - 若 `now - lastActiveAt > 10_000ms`,则认为该应用 **离线**,拒绝发送命令 - 否则认为 **在线**,允许发送命令 ## 5. 与本项目代码的对应关系 - **后端 `/api/projects`**:只从 `项目心跳`(LIST)读取项目列表,返回所有项目及其在线状态 - **后端 `/api/commands`**:从 `项目心跳` 中查找目标项目的 `apiBaseUrl/lastActiveAt`,在线时调用目标项目 API - **后端 `/api/logs`**:读取 `${projectName}_项目控制台`(LIST);并基于 `项目心跳` 中该项目的 `lastActiveAt` 计算在线/离线与 API 地址信息 ## 6. 兼容与错误处理建议 - JSON 解析失败:外部项目应记录错误,并丢弃该条消息(避免死循环阻塞消费)。 - 消息过长:建议控制单条消息大小(例如 < 64KB)。 - 字符编码:统一 UTF-8。 - 心跳超时:建议外部项目每 3 秒更新一次心跳,避免被误判为离线。 ## 7. 数据迁移工具(旧数据导入) 如果需要从旧格式迁移到新格式,可使用以下 API: ```bash POST /api/projects/migrate Content-Type: application/json { "deleteOldKeys": false, "dryRun": false } ``` 参数说明: - `deleteOldKeys`:是否删除旧格式键(默认 false) - `dryRun`:是否仅模拟运行(默认 false) 返回示例: ```json { "success": true, "message": "数据迁移完成", "migrated": 2, "projects": [...], "listKey": "项目心跳", "deleteOldKeys": false } ```