232 lines
10 KiB
Markdown
232 lines
10 KiB
Markdown
# PRD ① 设备端(rk3588-agent + media-server)远程管理能力(V1)
|
||
|
||
## 1. 背景
|
||
当前 `media-server` 已提供 HTTP 控制台与配置热更新能力(`/api/*`、`/api/config/reload`、`/api/config/rollback` 等)。由于 **大文件模型上传** 在现有 C++ 自研 HTTP Server 上实现成本较高(需要流式接收/写盘/校验/限流),本期采用更工程化的拆分:
|
||
|
||
- `media-server`:继续专注业务图(推理/推流/报警)与热更新。
|
||
- `rk3588-agent`(Go 新增常驻进程):对外提供局域网管理面能力:UDP 发现、模型/配置上传落盘、触发 `media-server` reload/rollback、代理读取 graphs/logs。
|
||
|
||
> 本 PRD 覆盖“轻量热更新/重载/回滚(业务图级)”。systemd/重启系统等运维级操作可作为后续扩展,但不作为 V1 验收项。
|
||
|
||
## 2. 目标
|
||
1. 管理端可通过 UDP 广播在 1 秒内发现同网段 10 台设备(由 `rk3588-agent` 响应)。
|
||
2. 管理端可通过 `rk3588-agent` 上传配置 JSON,设备端原子写入后触发 `media-server` reload 生效。
|
||
3. 管理端可通过 `rk3588-agent` 上传模型文件到设备固定目录,并返回可直接在配置中引用的 `model_path`。
|
||
4. 所有对外写操作必须鉴权(Token),读操作默认可不鉴权(可配置)。
|
||
|
||
## 3. 非目标(V1 不做)
|
||
- systemd start/stop/restart `media-server`(可在 agent 后续扩展)
|
||
- 设备重启/固件升级/插件升级
|
||
- 跨网段发现(保留后端可做网段扫描 fallback)
|
||
- 完整 RBAC/用户体系
|
||
|
||
## 4. 现状可复用能力(不修改语义)
|
||
- HTTP Server:`src/http_server.cpp`
|
||
- Graph/热更新:`GraphManager::ReloadFromFile`、`GraphManager::RollbackFromLastGood`
|
||
- 配置 Expand + Validate:`utils/config_expand.*`、`utils/config_schema.h`
|
||
- 运行状态:`GET /api/graphs`、`GET /api/graphs/{name}`、`GET /api/logs/recent`
|
||
|
||
## 5. 新增功能范围(V1)
|
||
|
||
### 5.1 新增进程:rk3588-agent(Go)
|
||
`rk3588-agent` 作为常驻服务,提供:
|
||
|
||
- UDP 广播发现(Option A):对管理端 Search 做响应。
|
||
- HTTP 管理 API(对外):模型上传、配置下发、触发 reload/rollback、代理 graphs/logs。
|
||
- 本地调用 `media-server`:通过 `http://127.0.0.1:<media_port>/api/...` 触发 reload/rollback/读取 graphs/logs。
|
||
|
||
#### 5.1.1 agent 代码目录结构(建议,开发可直接照此建工程)
|
||
建议以 Go module 形式独立工程(可放在同仓库 `agent/` 目录,也可独立仓库)。
|
||
|
||
```text
|
||
agent/
|
||
go.mod
|
||
cmd/
|
||
rk3588-agent/
|
||
main.go
|
||
internal/
|
||
config/ # 读取/校验 /etc/rk3588-agent/config.json
|
||
discovery/ # UDP 35688 discover responder
|
||
httpapi/ # 对外 HTTP 路由:/v1/* + auth
|
||
mediaserver/ # 对内 HTTP client:调用 127.0.0.1:9000/api/*
|
||
modelstore/ # 模型落盘/sha256/manifest
|
||
files/ # 原子写盘(tmp+rename)、权限校验
|
||
sysinfo/ # hostname/ip/uptime/device_id
|
||
log/ # 统一日志封装(stdout/journald)
|
||
```
|
||
|
||
### 5.2 media-server 变更范围(V1)
|
||
V1 目标是将大文件上传从 `media-server` 移出,因此 **media-server 可不新增大文件上传接口**。仅要求:
|
||
|
||
- 保持现有 `/api/config/reload`、`/api/config/rollback`、`/api/graphs`、`/api/logs/recent` 等接口可用。
|
||
- (可选安全加固,非 V1 必须)限制 `media-server` HTTP 仅监听 `127.0.0.1` 或对写接口增加 Token 鉴权。
|
||
|
||
## 6. 配置与落盘约定
|
||
|
||
### 6.1 新增 agent 配置项(建议)
|
||
agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议:
|
||
|
||
```json
|
||
{
|
||
"agent": {
|
||
"listen": "0.0.0.0:9100",
|
||
"token": "CHANGE_ME",
|
||
"require_token_for_read": false,
|
||
"discovery_enable": true,
|
||
"discovery_port": 35688,
|
||
"device_name": "rk3588-cam-01",
|
||
"device_id_path": "/var/lib/rk3588-agent/device_id",
|
||
"models_dir": "/opt/rk3588sys/models",
|
||
"max_upload_mb": 200,
|
||
"config_path": "/etc/rk3588sys/config.json",
|
||
"media_server_base_url": "http://127.0.0.1:9000",
|
||
"media_server_timeout_ms": 3000,
|
||
"media_server_retry": { "max_attempts": 3, "backoff_ms": [200, 500] }
|
||
}
|
||
}
|
||
```
|
||
|
||
字段说明(V1 关键字段):
|
||
- `config_path`:agent 写入配置文件的目标路径(与 media-server `--config` 一致)。
|
||
- `device_id_path`:device_id 持久化文件路径(不存在则自动生成并写入)。
|
||
- `media_server_base_url`:agent 调用 media-server 的本机地址,建议固定 `127.0.0.1`。
|
||
- `media_server_timeout_ms`:agent 调用 media-server 的 HTTP 总超时。
|
||
- `media_server_retry`:仅对“控制类请求”(reload/rollback)启用的重试策略。
|
||
|
||
### 6.2 设备侧文件系统布局(部署约定)
|
||
为保证权限与可维护性,约定如下路径:
|
||
|
||
- 可执行文件:
|
||
- `/opt/rk3588sys/bin/media-server`
|
||
- `/opt/rk3588sys/agent/rk3588-agent`
|
||
- 配置文件:
|
||
- `/etc/rk3588sys/config.json`(media-server `--config` 指向)
|
||
- `/etc/rk3588-agent/config.json`
|
||
- 状态/持久化:
|
||
- `/var/lib/rk3588-agent/device_id`
|
||
- 模型仓库:
|
||
- `/opt/rk3588sys/models/manifest.json`
|
||
- `/opt/rk3588sys/models/files/*.rknn`
|
||
|
||
> 说明:如不希望以 root 运行,可将 `config_path` 改到 `/opt/rk3588sys/config/config.json` 并给 agent 用户写权限;V1 为减少权限复杂度,建议 agent 以 root 运行。
|
||
|
||
### 6.3 systemd service(部署字段,开发/运维可直接照抄)
|
||
|
||
#### 6.3.1 rk3588-agent.service
|
||
路径建议:`/etc/systemd/system/rk3588-agent.service`
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=RK3588Sys Agent
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
ExecStart=/opt/rk3588sys/agent/rk3588-agent --config /etc/rk3588-agent/config.json
|
||
Restart=always
|
||
RestartSec=2
|
||
WorkingDirectory=/
|
||
LimitNOFILE=65535
|
||
|
||
# 可选:基础加固(需要确认路径)
|
||
NoNewPrivileges=true
|
||
PrivateTmp=true
|
||
ProtectHome=true
|
||
ProtectSystem=full
|
||
ReadWritePaths=/etc/rk3588sys /etc/rk3588-agent /opt/rk3588sys/models /var/lib/rk3588-agent
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
#### 6.3.2 media-server.service(建议统一纳入部署约定)
|
||
路径建议:`/etc/systemd/system/media-server.service`
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=RK3588Sys Media Server
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
ExecStart=/opt/rk3588sys/bin/media-server --config /etc/rk3588sys/config.json
|
||
Restart=always
|
||
RestartSec=2
|
||
LimitNOFILE=65535
|
||
|
||
# (可选)性能调参:多路推理并发 / RGA 并发
|
||
Environment=RK3588_RKNN_CTX_POOL_SIZE=3
|
||
Environment=RK3588_RGA_MAX_INFLIGHT=2
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
> V1 不要求 agent 控制 systemd,但要求两服务可开机自启。
|
||
|
||
### 6.5 性能调参说明(新增)
|
||
- `RK3588_RKNN_CTX_POOL_SIZE`:同一模型的 RKNN context 池大小(默认 3)。
|
||
- `RK3588_RGA_MAX_INFLIGHT`:RGA 全局并发上限(默认 2)。
|
||
|
||
### 6.4 模型目录结构
|
||
- `${models_dir}/manifest.json`
|
||
- `${models_dir}/files/<name>__<sha256>.<ext>`(`ext` 默认 `rknn`,白名单控制)
|
||
|
||
## 7. 约束与安全
|
||
- agent 对外写接口必须 `X-RK-Token`。
|
||
- 上传限制:必须 `Content-Length`;大小不得超过 `max_upload_mb`。
|
||
- agent 写盘采用原子写(临时文件 + rename)。
|
||
- agent 与 `media-server` 的本地通信固定走 `127.0.0.1`(避免暴露内部控制面)。
|
||
|
||
### 7.1 agent 内部调用 media-server 的 URL/超时/重试策略
|
||
agent 只调用 media-server 的既有接口(对内 base URL = `media_server_base_url`):
|
||
|
||
- Reload:`POST {base}/api/config/reload`
|
||
- Rollback:`POST {base}/api/config/rollback`
|
||
- Graphs:`GET {base}/api/graphs`
|
||
- Graph detail:`GET {base}/api/graphs/{name}`
|
||
- Logs:`GET {base}/api/logs/recent?limit=...`
|
||
|
||
超时策略(建议默认值):
|
||
- 读接口(graphs/logs):总超时 `1000ms`(不重试)
|
||
- 控制接口(reload/rollback):总超时 `media_server_timeout_ms`(默认 `3000ms`),允许重试
|
||
|
||
重试策略(仅控制接口):
|
||
- `max_attempts = 3`(首次 + 2 次重试)
|
||
- 触发条件:连接失败/超时/5xx(不对 4xx 重试)
|
||
- backoff:`[200ms, 500ms]`
|
||
|
||
配置下发联动策略(`PUT /v1/config`):
|
||
1) agent 原子写入 `config_path`
|
||
2) 调用 reload(按控制接口重试策略)
|
||
3) 若 reload 最终失败:调用 rollback(按控制接口重试策略)
|
||
4) 返回 500,错误消息包含 reload 与 rollback 的结果(便于定位)
|
||
|
||
### 7.2 启动顺序与可用性
|
||
- 建议 systemd 启动顺序:两者都 After network-online。
|
||
- agent 对外可先起来;当 media-server 尚未启动时:
|
||
- `/v1/graphs`、`/v1/logs/recent` 返回 500(error=connect refused/timeout)
|
||
- `/v1/config` 返回 500(写盘可成功,但 reload 失败会触发 rollback;错误信息提示 media-server 不可用)
|
||
|
||
## 8. 验收标准(Acceptance Criteria)
|
||
1. 同网段 10 台设备,管理端 Search(UDP broadcast)在 1 秒内都能发现;列表包含 `device_id/ip/agent_port/media_port/version/git_sha`。
|
||
2. agent `PUT /v1/config`:
|
||
- 发送合法 config,设备写盘并触发 `media-server` reload 成功,graphs 状态正常。
|
||
- 发送非法 config,agent 返回 400;或 reload 失败则 agent 自动 rollback 并返回 500(错误信息可定位)。
|
||
3. agent `PUT /v1/models/{name}`:上传成功返回 sha256/path;在配置中引用该 path 并 reload 后,相关节点能正常 Init(以日志/metrics 验证)。
|
||
4. 无 token 调用写接口返回 401;错误返回 JSON:`{"error":"..."}`。
|
||
|
||
## 9. 开发任务拆分(建议)
|
||
- [ ] 新增 `rk3588-agent`:HTTP 服务 + Token 鉴权 + 日志
|
||
- [ ] UDP discovery:协议解析/回复、device_id 获取与持久化、停止逻辑
|
||
- [ ] `GET /v1/info`:聚合 device/version/git_sha/ports/uptime
|
||
- [ ] `PUT /v1/config`:原子写盘 + 触发 `media-server` reload;失败自动 rollback
|
||
- [ ] `PUT /v1/models/{name}`:流式落盘 + sha256 + manifest 写入
|
||
- [ ] `GET /v1/models`:读取 manifest
|
||
- [ ] 代理接口:graphs、graph detail、logs recent、reload、rollback
|
||
- [ ] 统一错误码与日志(见接口清单表)
|