visionA/docs/autoflow/04-architecture/adr/adr-002-tunnel-protocol.md
jim800121chen fb7da5d180 chore(autoflow): migrate .autoflow/ 共享層文件至 docs/autoflow/
依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類
共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git),
讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等
per-branch 筆記。

- 02-prd/        21 個檔(PRD、features、market-analysis 等)
- 03-design/     18 個檔(design-spec、wireframes、flows 等)
- 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等)
- 07-delivery/   3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup)

合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv,
但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
2026-05-04 16:55:55 +08:00

92 lines
5.5 KiB
Markdown
Raw Permalink 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.

# ADR-002沿用 POC 的 Tunnel 協定WebSocket + yamux
## 狀態
Accepted — 2026-04-21
## 背景 (Context)
visionA Cloud 最核心的技術要素是:**瀏覽器透過雲端反向代理,操作使用者本地電腦上的 Kneron 裝置**。
這要求在「雲端 Proxy」與「使用者電腦的 local agent」之間建立一條
- **由 local agent 主動出站建立**(穿越 NAT / 企業防火牆)
- **雙向多工**:同時傳遞 HTTP 控制指令、長輪詢 WebSocket、MJPEG 串流、推論結果串流
- **低延遲**:串流資料需保留 real-time 特性
- **可重連**:網路短暫斷線後自動恢復
POCedge-ai-platform已用 **WebSocket + hashicorp/yamux** 實作並驗證可行:
- 外層 `gorilla/websocket` 負責「由 client 發起、能穿越企業代理」
- 內層 `yamux` 把單條 WebSocket 升級為多工 stream每個 HTTP 請求開一條 yamux stream
- WebSocket binary frame 之上用 `wsconn` adapter 把 WebSocket 包成 `net.Conn`
POC 源碼重點:
- `relay/server.go`:收 `/tunnel/connect`、建立 `yamux.Server(netConn)`、按 token 收在 `map[token]*yamux.Session`
- `tunnel/client.go`Dial WebSocket → `yamux.Client()` → 接收 stream → 轉給本機 `127.0.0.1:3721`
- `pkg/wsconn/wsconn.go``websocket.Conn``net.Conn` adapterbinary frame
## 決策 (Decision)
**雛形沿用 POC 的 tunnel 協定不做重大改變**
- 外層:`github.com/gorilla/websocket`version ≥ 1.5.3
- 多工:`github.com/hashicorp/yamux`default config
- Adapter把 POC 的 `wsconn` 搬到 `visionA-backend/internal/wsconn`(或 `pkg/wsconn`,視是否對外暴露)
- 端點:`WS /tunnel/connect?token=xxx`remote-proxy 側)
- 訊息語義:沿用 POC 的「yamux stream 裡傳完整 HTTP request/response」
**沿用的好處:代碼已在 POC 驗證過能穿越 NAT、能處理 WebSocket upgrade`proxyWebSocket` 的 Hijack 邏輯)、能處理 MJPEG streaming。**
**雛形會升級的部分(與 ADR-003 相關)**
- Token 生成機制SHA256(MAC) → Pairing Token詳見 ADR-003
- `handleTunnel` 加上 token 驗證 hook雛形驗 env 寫死 token未來驗 DB
- Session 管理抽 interface雛形 in-memory未來 Redis詳見 ADR-001
**未來可能會重新評估的項目(非雛形範疇)**
- 若 stream 吞吐或 head-of-line blocking 成瓶頸 → 評估 HTTP/3 (QUIC) 或 gRPC bidi stream
- 若需要端對端加密(繞過雲端看到明文)→ 在 yamux 之上再包一層 TLS / Noise
- 若需要跨雲的地理就近路由 → 加入 proxy routing 層,由 local agent 選擇 entrypoint
## 考慮過的替代方案
| 方案 | 優點 | 缺點 | 排除原因 |
|------|------|------|---------|
| **重頭設計 gRPC bidi stream** | 現代 RPC有 code-gen、型別安全 | 要重新定義所有訊息 schemaPOC 已用 HTTP semantics 讓搬遷成本低 | 雛形期不值得,未來可升級 |
| **HTTP/3 (QUIC) 原生多工** | 未來標準、天生多工、零 HOL blocking | Go 生態的 QUIC 客戶端 / 伺服器還在 beta反向代理成熟度低 | 還太新 |
| **單一 WebSocket 無多工(每請求新開 WS** | 最簡單 | 每請求一次 WS handshake~50-200ms串流無法疊加 | 效能差 |
| **SSH tunnel / WireGuard 等 VPN 方案** | 標準 | 需要使用者端安裝額外軟體、開特定埠、難穿越企業防火牆 | 使用者體驗差 |
| **純 TCP tunnel over TLS** | 簡單 | 通常被企業防火牆封鎖WebSocket 因為外觀像 HTTP 能穿透 | 穿透力差 |
## 後果 (Consequences)
### 正面影響
- **零移植成本**POC relay / tunnel 程式碼可直接搬到 `visionA-backend/internal/relay``visionA-backend/internal/tunnel`
- **已驗證 NAT 穿透**POC 測試過能穿越公司 NAT、家用路由器 NAT
- **已驗證 WebSocket-in-WebSocket**:瀏覽器 → Proxy → tunnel stream → local agent 的 WebSocket upgrade 流程POC 的 `proxyWebSocket` 已處理 Hijack 並雙向 pipe這個最難的部分已經能跑
- **已驗證 MJPEG streaming**POC 的 `handleProxy``http.Flusher` 處理串流回應visionA 的 camera stream 可直接用
- **擴展空間大**yamux 天生多工,一個 tunnel 可以同時跑 10+ 個 HTTP 請求不互相阻塞
### 負面影響(接受的取捨)
- **訊息格式是 HTTP 明文**yamux stream 內跑的是 raw HTTP request/response需靠 TLSWebSocket 外層保密Proxy 節點可以看到明文請求內容
- **yamux 依賴**hashicorp/yamux 已久無大版本更新,但 v0.x 穩定
- **單 WebSocket = 單 tunnel**:一個 local agent 一條 WebSocket若要跨地理區域 active-active需應用層路由
- **HOL blocking 風險低但存在**yamux 是多工,但底層單一 TCP connection若網路抖動整條都延遲
### 風險
- **WebSocket 升級失敗率**:企業防火牆 / 中間人代理可能阻擋 WebSocket upgrade。雛形先不處理 fallbackSSE / long-pollTODO
- **單條 WebSocket 頻寬極限**:若使用者端上傳 MJPEG 4K 60fps 會打滿一條 TCP。實測後若有問題再引入「多條 WebSocket + 分流」
- **yamux 的 keepalive**POC 用 default config是否足夠穿越企業 idle timeoutTODO 壓測驗證
## 合規性
- [x] Architect 確認
- [x] POC 實測驗證(`edge-ai-platform` 已部署到 EC2 + 本地測試)
- [ ] 未來壓測TODO
## 相關文件
- Design Doc §3資料流
- TDD §6Tunnel 協定)
- TDD §7Session 管理)
- POC 源碼:`edge-ai-platform/server/internal/{relay,tunnel}``edge-ai-platform/server/pkg/wsconn`