哪吒 Dashboard、Agent 与 gRPC 的协作架构

解释 Dashboard、Agent、反向代理、CDN 与数据库如何共同完成状态采集和远程任务。

#type / synthesis #status / evergreen #tech / ops #tech / network #resource / nezha #protocol / grpc #platform / server

哪吒 Dashboard、Agent 与 gRPC 的协作架构

[!info] related notes

[!abstract] 核心结论 “网页能打开”只证明 Web 链路可用;Agent 上线还要求同一入口完整通过 TLS、HTTP/2、gRPC 路径、鉴权头和长连接。

数据流不是一条普通网页请求

sequenceDiagram
    participant A as Agent
    participant E as DNS/CDN/反向代理
    participant D as Dashboard
    participant DB as SQLite
    A->>E: TLS + HTTP/2 gRPC 建连
    E->>D: 转发 /proto.NezhaService/*
    D->>D: 校验用户密钥与 Agent UUID
    D->>DB: 查找或创建服务器记录
    A->>D: 周期上报系统信息
    D->>DB: 保存配置与关系数据
    D-->>A: 任务、配置或控制消息

初次连接时,Dashboard 根据用户连接密钥确定归属,再根据 UUID 识别数据源。之后 Agent 周期性上报状态。远程命令、终端和配置下发则沿已建立的控制通道返回 Agent。

四个必须同时成立的不变量

  1. server 指向的主机和端口在网络层可达。
  2. tls: true 时,域名、证书和 SNI 必须匹配,除非明确接受不安全验证。
  3. 反向代理必须把 /proto.NezhaService/* 作为 gRPC 转发到 Dashboard 的 h2c 后端。
  4. client_secret 与用户身份匹配,uuid 在每个逻辑 Agent 上保持稳定且唯一。

只满足前三项会得到鉴权错误;只满足 Web 页面访问会在 gRPC 探测时得到 HTML、403、404 或 502。

V1 之后为什么 Web 与 gRPC 共用端口

V1 起 Dashboard 的 Web 与 gRPC 默认共用 8008。这减少了需要暴露和维护的端口,但把协议分流责任交给反向代理:普通 HTTP/WebSocket 与 gRPC 使用同一域名时,代理必须根据路径和协议选择正确的上游传输。

CDN 有两种可行策略

策略Web 访问Agent 通信主要代价
双域名CDN 域名DNS-only 通信域名多维护一个域名,行为最清晰
单域名CDN 域名同一 CDN 域名且启用 gRPC依赖 CDN 的 gRPC、HTTP/2 和安全规则
客户端 hosts 直连CDN 域名保留 SNI 但解析到源站源站必须放行 Agent IP,源站 IP 变更需同步

Cloudflare 未启用 gRPC 时会直接对 gRPC 请求返回 403 Forbidden。这不会影响普通网页,因此容易造成“面板正常但 Agent 全离线”的错觉。

最小协议验证

curl --http2 -v \
  -H 'Content-Type: application/grpc' \
  -X POST \
  https://data.example.com/proto.NezhaService/

健康的协议入口通常返回 HTTP/2、content-type: application/grpc,并以 grpc-status: 12 表示调用了未知方法。这个结果不是业务成功,但证明请求已经穿过 TLS、CDN/代理并到达 gRPC 服务。

资料来源

创建于 2026/7/20 更新于 2026/7/20