Files
pikasTech-HWLAB/docs/reference/gateway-outbound-demo.md
T
2026-05-29 15:01:56 +08:00

91 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gateway 主动出站 demo
本文是 `hwlab-gateway` 最小主动出站闭环的长期参考。该 demo 只验证 gateway 主动连接 cloud、cloud 下发命令、gateway 执行并回传结果;不得把它当作 M3 `DEV-LIVE` 虚拟硬件可信闭环,也不得替代 `BOX-SIMU / Gateway-SIMU / hwlab-patch-panel` 的 M3 验收链路。
## 边界
- `hwlab-gateway` 运行在用户 PC 或本地环境,主动访问 `hwlab-cloud-api`;cloud 不需要也不应入站访问 gateway。
- demo 采用普通 HTTP poll/resultgateway 调 `POST /v1/gateway/poll` 拉取命令,执行后调 `POST /v1/gateway/result` 回传 JSON-RPC response。
- `hardware.invoke.shell` 仍是 cloud-api 对外 RPC 方法;有在线 gateway 时通过主动出站链路派发,没有在线 gateway 时保留 `not_connected` 降级返回。
- 当前命令执行能力只用于受限 demo;正式真实硬件控制以 [spec-device-pod.md](spec-device-pod.md) 和 [spec-user-access.md](spec-user-access.md) 为权威:用户权限由 `cloud-api``admin/user` 与 device pod grant 判断,不拆 capability;设备执行收敛到 `cloud-api -> hwlab-device-pod -> gateway`,硬件 trace/evidence/audit 只作为硬件证据链,不作为用户权限模型。
## Cloud API 入口
- `GET /v1/gateway/sessions`:只读查看在线 gateway、队列深度和 last-seen。
- `POST /v1/gateway/poll`:gateway 主动注册、心跳并领取下一条待执行 JSON-RPC 请求。
- `POST /v1/gateway/result`gateway 主动回传 JSON-RPC responsecloud-api 用 request id 完成等待中的 `hardware.invoke.shell`
- `POST /json-rpc``POST /v1/rpc/hardware.invoke.shell`:用户、agent 或 smoke 仍只调用 cloud-api,不直连 gateway。
## Poll Loop 和长命令并发
Gateway 的 poll loop 不能等待单条 shell 命令结束后才继续 poll。Keil build/download、烧录或 Windows skill 可能运行数分钟;这些长命令必须在 gateway 内作为 in-flight 请求后台执行,poll loop 继续注册心跳并领取短状态读取、日志读取和取消/诊断请求。
判断问题类型时区分两种 timeout:
- `shellExecuted=true` 且有 `operationId`:命令已经到达 gateway,本次 shell 超过了命令超时;下一步应读取 job state、日志或产物时间戳,而不是盲目把超时继续调大。
- `shellExecuted=false``dispatchStatus=timed_out` 且旧链路可能 `operationId=null`cloud-api 等不到 gateway 领取或回传,通常是 gateway poll loop 被前一个长命令队头阻塞,或 gateway 离线;修复重点是非阻塞 poll 和 in-flight 可观测性,不是只加大 dispatch timeout。
Gateway 必须在 registration payload 和 `/v1/gateway/sessions` 中暴露 `inflightCount``maxInflightRequests` 和当前 in-flight 摘要。默认允许少量并发,使一个长 Keil 操作不会阻塞后续只读 `job-status`、state/log 读取或健康探测;超过并发上限时应返回结构化 `gateway_busy`,不能让请求静默排队到 cloud dispatch timeout。
## Gateway 环境变量
| 变量 | 作用 |
| --- | --- |
| `HWLAB_GATEWAY_CLOUD_URL` | cloud-api 或 edge-proxy 地址;本地可用 `http://127.0.0.1:6667`,当前 G14 DEV 可用 `http://74.48.78.17:17667`。 |
| `HWLAB_GATEWAY_ID` | gateway 稳定身份,例如 `gtw_windows_1`。 |
| `HWLAB_GATEWAY_SESSION_ID` | gateway session id;不填时默认为 `gws_${HWLAB_GATEWAY_ID}`。 |
| `HWLAB_GATEWAY_CMD_EXEC_ENABLED=1` | 允许执行 shell 命令;未设置时 gateway 拒绝 `hardware.invoke.shell`。 |
| `HWLAB_GATEWAY_DEMO_OPEN=1` | demo 明确打开标记;本地 smoke 会设置。 |
| `HWLAB_GATEWAY_POLL_INTERVAL_MS` | poll 间隔,默认 500ms。 |
| `HWLAB_GATEWAY_MAX_INFLIGHT` | 同一 gateway 同时执行的 cloud 请求数,默认 3;用于避免长 Keil/UV4 命令阻塞短状态查询。 |
| `HWLAB_GATEWAY_CMD_TIMEOUT_MS` | 单条命令超时,默认 120000msWorkbench 发起 Code Agent 请求时可通过“Gateway 命令超时”控件把本轮 wrapper `--timeout-ms` 调到 1/2/3/5/10 分钟。 |
| `HWLAB_GATEWAY_CMD_OUTPUT_LIMIT_BYTES` | stdout/stderr 单路输出上限,默认 65536 bytes。 |
本地或内网存在代理时,必须显式设置:
```powershell
$env:NO_PROXY="localhost,127.0.0.1,::1"
$env:no_proxy="localhost,127.0.0.1,::1"
```
## 本地验证
优先使用一键 smoke,避免手动多终端状态不一致:
```powershell
npm run gateway:demo:smoke
npm run gateway:demo:edge-smoke
```
- `gateway:demo:smoke` 启动本地 `hwlab-cloud-api``hwlab-gateway`,验证 `hardware.invoke.shell` 返回 `stdout=hwlab-demo`
- `gateway:demo:edge-smoke` 额外启动本地 `hwlab-edge-proxy`,验证普通 HTTP proxy 能转发 `/v1/gateway/poll``/v1/gateway/result``/json-rpc`
- 两个 smoke 都会设置 `NO_PROXY/no_proxy`,用于规避本地代理误触发。
- 对 G14 pod 内部 `127.0.0.1:6667` 或 service `:6667` 做 Node 探测时,不要用 Web/undici `fetch``6667` 属于 WHATWG bad portNode 会直接报 `bad port`。gateway 传输层和 repo-owned 探测脚本应使用 `http/https` 原生 request,公网 `:17667` 或浏览器入口不受这个限制。
## DEV 使用
DEV cloud-api 部署包含 `/v1/gateway/*` 后,Windows gateway 可用以下方式主动连接:
```powershell
$env:HWLAB_GATEWAY_CLOUD_URL="http://74.48.78.17:17667"
$env:HWLAB_GATEWAY_ID="gtw_windows_1"
$env:HWLAB_GATEWAY_SESSION_ID="gws_gtw_windows_1"
$env:HWLAB_GATEWAY_CMD_EXEC_ENABLED="1"
$env:HWLAB_GATEWAY_DEMO_OPEN="1"
bun run .\cmd\hwlab-gateway\main.ts
```
验证时从 cloud-api 侧调用 `hardware.invoke.shell`,不要尝试从 cloud 入站访问 Windows gateway。若 `GET /v1/gateway/sessions` 能看到对应 `gatewaySessionId` 且 JSON-RPC 返回 `dispatch.shellExecuted=true`,说明主动出站 demo 链路成立。
## 后续替换为 WebSocket
HTTP poll 是最小 demo 形态。后续替换成 WebSocket 时,应保留:
- `hardware.invoke.shell` 对外 RPC 方法名;
- JSON-RPC request/response envelope
- gateway 执行器的 stdout/stderr/exitCode/timedOut 返回形态;
- audit/evidence 由 gateway/cloud 硬件通道产生的原则;
- cloud-web、agent 和 CLI 不直连 gateway 的边界。
只替换传输层:`/v1/gateway/poll``/v1/gateway/result` 合并到 gateway 主动建立的 `/v1/gateway/ws` 长连接。