更新readme
This commit is contained in:
parent
f309e2d576
commit
3efa303afd
327
Readme.md
327
Readme.md
@ -1,64 +1,96 @@
|
||||
# PRD ③ 管理端后端(Go managerd)V1
|
||||
# managerd
|
||||
|
||||
## 1. 目标与运行方式
|
||||
`managerd` 是 RK3588 管理端后端服务,负责设备发现、设备注册表维护、代理访问设备端 `rk3588-agent`,并提供内嵌 Web UI、OpenAPI 页面和 HTTP API。
|
||||
|
||||
- 提供本机 HTTP API 给 React UI 使用。
|
||||
- 负责 UDP 广播发现(Option A),维护设备缓存与在线状态。
|
||||
- 通过设备端 `rk3588-agent` 完成配置/模型等运维操作,并可通过 agent 代理读取 graphs/logs。
|
||||
- 支持批量任务(并发、进度、失败原因)并通过 SSE 推送。
|
||||
## 当前状态
|
||||
|
||||
运行:单可执行 `managerd`,默认监听 `127.0.0.1:18080`(可配置)。
|
||||
- 提供 HTTP API,供前端或其他本地工具调用。
|
||||
- 内嵌 Web UI,启动后可直接在浏览器访问。
|
||||
- 支持 UDP 广播发现设备,并维护内存中的设备在线状态。
|
||||
- 支持代理访问设备端 agent 的常用接口,以及 `/v1/*` 通用透传。
|
||||
- 支持批量任务执行,并通过 SSE 推送逐设备状态。
|
||||
- 模板从本地 `templates/*.json` 读取。
|
||||
|
||||
## 2. 外部依赖与约束
|
||||
## 运行方式
|
||||
|
||||
- Go 版本:>= 1.22(建议)
|
||||
- 标准库优先;Web 框架可选 `chi`/`gin`(建议 chi + net/http)。
|
||||
- 不需要数据库(V1 用内存 + 可选本地 JSON 持久化)。
|
||||
默认通过单个可执行文件运行:
|
||||
|
||||
## 3. 模块划分
|
||||
```bash
|
||||
managerd
|
||||
```
|
||||
|
||||
### 3.1 Discovery
|
||||
也可以指定配置文件路径:
|
||||
|
||||
- 向所有可用网卡的广播地址发送 UDP discover。
|
||||
- 监听本地 UDP socket 收集 replies(时间窗默认 1200ms)。
|
||||
- 去重规则:按 `device_id` 去重,以最新 reply 为准。
|
||||
```bash
|
||||
managerd path/to/managerd.json
|
||||
```
|
||||
|
||||
### 3.2 Device Registry
|
||||
程序启动后:
|
||||
|
||||
- 内存缓存:
|
||||
- `device_id -> {ip, agent_port, media_port, device_name, version, git_sha, last_seen_ms, online}`
|
||||
- 定时刷新(可配置间隔):对 online 设备拉取 `GET /v1/graphs`(agent 代理),更新摘要。
|
||||
- Offline 规则:超过 `offline_after_ms`(如 10000ms)未见到,则标记离线。
|
||||
- `GET /` 会重定向到 `/ui`
|
||||
- `GET /ui` 为内嵌管理页面
|
||||
- `GET /openapi.json` 返回 OpenAPI 描述
|
||||
- `GET /health` 返回健康检查结果
|
||||
|
||||
### 3.3 Device Client
|
||||
当前仓库中的示例配置监听地址为 `0.0.0.0:18080`。
|
||||
|
||||
- 统一超时:connect 1s、overall 3s(可配置)。
|
||||
- 统一错误包装:返回 `error_code + message + device_id`。
|
||||
- Token:
|
||||
- 全局默认 token(V1)
|
||||
- 可预留 per-device token(P1)
|
||||
## 依赖
|
||||
|
||||
### 3.4 Templates/Config Builder
|
||||
- Go `1.23.3`
|
||||
- `github.com/go-chi/chi/v5`
|
||||
- `github.com/go-chi/cors`
|
||||
- `github.com/google/uuid`
|
||||
|
||||
- 模板库来源:
|
||||
- V1:managerd 内置(embed)或本地 `templates/` 目录读取
|
||||
- 返回前端表单 schema:V1 允许手工维护(避免解析占位符带来的不确定性)。
|
||||
- 生成 root config:基于模板与 params,产出 `{global,templates,instances}`。
|
||||
## 主要模块
|
||||
|
||||
### 3.5 Task Runner
|
||||
### Discovery
|
||||
|
||||
- 任务类型:
|
||||
- `config_apply`(对 N 台设备下发 config)
|
||||
- 向所有可用广播网卡发送 UDP discover 请求
|
||||
- 在本地临时 UDP 端口监听回复
|
||||
- 按 `device_id` 去重,并使用最新回复更新注册表
|
||||
|
||||
### Device Registry
|
||||
|
||||
- 以内存维护设备列表
|
||||
- 每 2 秒执行一次离线判定
|
||||
- 超过 `offline_after_ms` 未更新则标记为离线
|
||||
- 每 30 秒对在线设备拉取一次 `GET /v1/graphs`,更新 `graphs` 字段
|
||||
- 除 UDP 发现外,成功代理调用设备接口时也会刷新设备 `last_seen_ms`
|
||||
|
||||
### Agent Client
|
||||
|
||||
- 默认 HTTP 请求超时为 3 秒
|
||||
- 对配置下发、模型上传、`/v1/config/ui/*`、人脸库上传等长操作使用 120 秒超时
|
||||
- 自动附带全局 `X-RK-Token`
|
||||
|
||||
### Template Service
|
||||
|
||||
- 从本地 `templates/` 目录加载 `.json` 模板
|
||||
- 返回模板列表和单个模板详情
|
||||
- 当前没有实现 embed 模板加载
|
||||
|
||||
### Task Runner
|
||||
|
||||
- 支持并发执行,默认并发数为 `concurrency`
|
||||
- 支持 SSE 推送逐设备状态
|
||||
- 当前支持的任务类型:
|
||||
- `config_apply`
|
||||
- `reload`
|
||||
- `rollback`
|
||||
- `model_upload`(V1 可先做单设备;批量后续)
|
||||
- 并发控制:默认 5(可配置)。
|
||||
- 状态:`pending/running/success/failed`(逐设备与整体)。
|
||||
- 推送:SSE `GET /api/tasks/:id/events`。
|
||||
- `media_start`
|
||||
- `media_restart`
|
||||
- `media_stop`
|
||||
|
||||
## 4. managerd 对前端 API 规格(V1)
|
||||
## API 概览
|
||||
|
||||
### 4.1 Discovery
|
||||
### 基础接口
|
||||
|
||||
- `GET /health`
|
||||
- `GET /openapi.json`
|
||||
- `GET /` -> 302 跳转到 `/ui`
|
||||
- `GET /ui`
|
||||
|
||||
### Discovery
|
||||
|
||||
#### `POST /api/discovery/search`
|
||||
|
||||
@ -71,62 +103,123 @@ Request:
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "items": [ {"device_id":"...","ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"..."} ] }
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"device_id": "...",
|
||||
"hostname": "...",
|
||||
"ip": "...",
|
||||
"agent_port": 9100,
|
||||
"media_port": 9000,
|
||||
"device_name": "...",
|
||||
"version": "...",
|
||||
"git_sha": "...",
|
||||
"uptime_sec": 0,
|
||||
"last_seen_ms": 0,
|
||||
"online": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Devices
|
||||
### Devices
|
||||
|
||||
#### `GET /api/devices`
|
||||
|
||||
Response:
|
||||
返回当前注册表中的设备列表:
|
||||
|
||||
```json
|
||||
{ "items": [ {"device_id":"...","online":true,"last_seen_ms":0,"ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"...","graphs":[...]} ] }
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"device_id": "...",
|
||||
"hostname": "...",
|
||||
"ip": "...",
|
||||
"agent_port": 9100,
|
||||
"media_port": 9000,
|
||||
"device_name": "...",
|
||||
"version": "...",
|
||||
"git_sha": "...",
|
||||
"uptime_sec": 0,
|
||||
"last_seen_ms": 0,
|
||||
"online": true,
|
||||
"graphs": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `GET /api/devices/:id`
|
||||
#### `POST /api/devices`
|
||||
|
||||
Response:包含 `info`、`graphs_summary`、`last_seen`。
|
||||
|
||||
### 4.3 Device actions(代理调用)
|
||||
|
||||
以下全部通过 agent:
|
||||
|
||||
- `POST /api/devices/:id/reload` → agent `POST /v1/media-server/reload`
|
||||
- `POST /api/devices/:id/rollback` → agent `POST /v1/media-server/rollback`
|
||||
- `GET /api/devices/:id/graphs` → agent `GET /v1/graphs`
|
||||
- `GET /api/devices/:id/graphs/:name` → agent `GET /v1/graphs/{name}`
|
||||
- `GET /api/devices/:id/logs?limit=200` → agent `GET /v1/logs/recent?limit=200`
|
||||
|
||||
### 4.4 Config apply
|
||||
|
||||
#### `POST /api/devices/:id/config/apply`
|
||||
|
||||
Request:
|
||||
手工添加一个设备到注册表:
|
||||
|
||||
```json
|
||||
{ "config": { } }
|
||||
{
|
||||
"device_id": "demo-device",
|
||||
"device_name": "Demo",
|
||||
"ip": "192.168.1.10",
|
||||
"agent_port": 9100,
|
||||
"media_port": 9000
|
||||
}
|
||||
```
|
||||
|
||||
Behavior:调用 agent `PUT /v1/config`。
|
||||
#### `GET /api/devices/{id}`
|
||||
|
||||
### 4.5 Model upload
|
||||
直接返回该设备对象。
|
||||
|
||||
#### `POST /api/devices/:id/models/upload`
|
||||
### 设备代理接口
|
||||
|
||||
Request:`multipart/form-data`,字段:
|
||||
以下接口由 managerd 转发到设备端 agent:
|
||||
|
||||
- `name`: string
|
||||
- `file`: binary
|
||||
- `GET /api/devices/{id}/info` -> `GET /v1/info`
|
||||
- `POST /api/devices/{id}/reload` -> `POST /v1/media-server/reload`
|
||||
- `POST /api/devices/{id}/rollback` -> `POST /v1/media-server/rollback`
|
||||
- `GET /api/devices/{id}/graphs` -> `GET /v1/graphs`
|
||||
- `GET /api/devices/{id}/graphs/{name}` -> `GET /v1/graphs/{name}`
|
||||
- `GET /api/devices/{id}/logs?limit=200` -> `GET /v1/logs/recent?limit=200`
|
||||
- `POST /api/devices/{id}/config/apply` -> `PUT /v1/config`
|
||||
- `GET /api/devices/{id}/models` -> `GET /v1/models`
|
||||
- `POST /api/devices/{id}/media-server/start` -> `POST /v1/media-server/start`
|
||||
- `POST /api/devices/{id}/media-server/restart` -> `POST /v1/media-server/restart`
|
||||
- `POST /api/devices/{id}/media-server/stop` -> `POST /v1/media-server/stop`
|
||||
- `GET /api/devices/{id}/media-server/status` -> `GET /v1/media-server/status`
|
||||
|
||||
Behavior:读取文件流,转发为 agent `PUT /v1/models/{name}`(raw body)。
|
||||
#### 通用透传
|
||||
|
||||
### 4.6 Templates
|
||||
- `ANY /api/devices/{id}/v1/*`
|
||||
|
||||
该路由会将 `/api/devices/{id}` 之后的路径原样透传到设备端 agent,可用于:
|
||||
|
||||
- `/v1/config`
|
||||
- `/v1/config/ui/schema`
|
||||
- `/v1/config/ui/state`
|
||||
- `/v1/config/ui/plan`
|
||||
- `/v1/config/ui/apply`
|
||||
- `/v1/face-gallery`
|
||||
- `/v1/face-gallery/reload`
|
||||
- 以及其他已存在的 `/v1/*` 接口
|
||||
|
||||
### 模型上传
|
||||
|
||||
#### `POST /api/devices/{id}/models/upload`
|
||||
|
||||
请求类型:`multipart/form-data`
|
||||
|
||||
字段:
|
||||
|
||||
- `name`: 模型名
|
||||
- `file`: 二进制文件
|
||||
|
||||
行为:managerd 读取上传文件,并转发为设备端 agent 的 `PUT /v1/models/{name}`。
|
||||
|
||||
### Templates
|
||||
|
||||
- `GET /api/templates`
|
||||
- `GET /api/templates/:name`
|
||||
- `GET /api/templates/{name}`
|
||||
|
||||
### 4.7 Tasks
|
||||
当前模板数据来自本地 `templates/*.json`。
|
||||
|
||||
### Tasks
|
||||
|
||||
#### `POST /api/tasks`
|
||||
|
||||
@ -135,51 +228,48 @@ Request:
|
||||
```json
|
||||
{
|
||||
"type": "config_apply",
|
||||
"device_ids": ["..."],
|
||||
"payload": { "config": {} }
|
||||
"device_ids": ["device-a", "device-b"],
|
||||
"payload": {
|
||||
"config": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `config_apply` 会将 payload 作为配置内容下发到 `/v1/config`
|
||||
- `media_start` 和 `media_restart` 可选接收 `{"config":"xxx"}` 形式的 payload
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "task_id": "..." }
|
||||
```
|
||||
|
||||
#### `GET /api/tasks/:id/events` (SSE)
|
||||
#### `GET /api/tasks`
|
||||
|
||||
Event `device_update` data:
|
||||
返回当前内存中的任务列表。
|
||||
|
||||
```json
|
||||
{ "device_id":"...","status":"running|success|failed","progress":0.0,"error":"" }
|
||||
```
|
||||
#### `GET /api/tasks/{id}/events`
|
||||
|
||||
## 5. 错误处理规范(managerd → 前端)
|
||||
|
||||
- 成功:2xx + `{"ok":true}` 或正常业务 JSON
|
||||
- 失败:4xx/5xx +
|
||||
|
||||
```json
|
||||
{ "error": { "code": "...", "message": "...", "device_id": "...", "detail": "..." } }
|
||||
```
|
||||
|
||||
建议错误码:
|
||||
|
||||
- `DISCOVERY_FAILED`
|
||||
- `DEVICE_NOT_FOUND`
|
||||
- `DEVICE_OFFLINE`
|
||||
- `DEVICE_HTTP_ERROR`
|
||||
- `DEVICE_TIMEOUT`
|
||||
- `TASK_NOT_FOUND`
|
||||
- `VALIDATION_ERROR`
|
||||
|
||||
## 6. 配置文件(managerd)建议
|
||||
|
||||
`managerd.json`:
|
||||
SSE 事件名为 `device_update`,数据格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"listen": "127.0.0.1:18080",
|
||||
"device_id": "...",
|
||||
"status": "running",
|
||||
"progress": 0.0,
|
||||
"error": ""
|
||||
}
|
||||
```
|
||||
|
||||
## 配置文件
|
||||
|
||||
`managerd.json` 示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"listen": "0.0.0.0:18080",
|
||||
"discovery_port": 35688,
|
||||
"discovery_timeout_ms": 1200,
|
||||
"offline_after_ms": 10000,
|
||||
@ -188,9 +278,28 @@ Event `device_update` data:
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 验收标准
|
||||
字段说明:
|
||||
|
||||
1. Search 可发现设备并更新 registry;离线判断正确。
|
||||
2. 可通过 agent 读取 graphs/logs(`GET /v1/graphs`、`GET /v1/logs/recent`)。
|
||||
3. 单设备 `config/apply`、`reload`、`rollback` 可用,错误可定位。
|
||||
4. 批量 `config_apply` 任务可并发执行并通过 SSE 输出逐台结果。
|
||||
- `listen`: managerd 监听地址
|
||||
- `discovery_port`: 设备发现广播端口
|
||||
- `discovery_timeout_ms`: 搜索超时
|
||||
- `offline_after_ms`: 多久未更新则视为离线
|
||||
- `agent_token`: 转发到设备端 agent 的统一 token
|
||||
- `concurrency`: 批量任务并发数
|
||||
|
||||
## 目录说明
|
||||
|
||||
- `cmd/managerd`: 程序入口
|
||||
- `internal/api`: API 路由与处理器
|
||||
- `internal/service`: discovery、registry、task、template、agent client
|
||||
- `internal/web`: 内嵌 Web UI
|
||||
- `templates`: 本地模板
|
||||
- `scripts/deploy`: 部署脚本
|
||||
|
||||
## 验证现状
|
||||
|
||||
当前仓库已通过:
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Loading…
Reference in New Issue
Block a user