服务端协议与多服务端容灾

专栏:VNT 2.0 组网源码 · 第 9 / 11 篇
VNT协议容灾

:::info 学习目标 完成本篇后你能够:列出服务端的四大职责与对应协议消息;解释多服务端协调注册的三步握手;说出三种传输协议与 dynamic:// 的发现机制。 前置:第 3、5 篇完成。预计时长:55 分钟。 :::

:::note 本章术语速查(新手建议先读)

  • 容灾:一台服务挂了,备用的无缝顶上。
  • 增量推送:只推“变化的部分”(带版本号对比),省流量。
  • TXT 记录:DNS 的一种记录,可存任意文本——VNT 用它动态发现服务端地址。
  • WSS:走 HTTPS 通道的 WebSocket,容易穿过只放行网页流量的网络。 :::

服务端 vnts 是独立项目(本仓库只有客户端侧的协议实现),但从 tunnel_core/server/ 与 proto/ 的协议定义可以精确还原它的四大职责。

服务端的四大职责

职责协议说明
① 注册与 IP 分配RegRequest/RegResponse/ConfirmReg同组网编号分配互不冲突的虚拟 IP
② 在线列表ClientSimpleInfoList(推送)+ client_list RPC谁在线、叫什么、什么版本
③ 中继转发Turn 密文透传无直连时的兜底通道(服务端只见密文)
④ 打洞撮合PunchStart1/2 转发交换双方 NAT 信息(第 6 篇)

注册协议全字段

// vnt-core/proto/control_message.proto:9-33(节选)
message RegRequestMsg {
  string network_code = 1;      // 组网编号
  string device_id = 2;         // 设备唯一标识(默认 machine uid)
  optional fixed32 ip = 3;      // 请求的固定 IP(可选)
  string name = 4;              // 设备名
  string version = 5;
  optional string key_sign = 6; // 口令指纹(第 5 篇)
  bool ip_variable = 7;         // 是否接受服务端改 IP
  fixed32 server_id = 8;
  RegistrationMode registration_mode = 9;  // NORMAL / PRE_REGISTER
}
message RegResponseMsg {
  fixed32 ip = 1;               // 分配的虚拟 IP
  uint32 prefix_len = 2;        // 网段前缀
  fixed32 gateway = 3;          // 虚拟网关
  string server_version = 4;
}

key_sign 让服务端校验”同编号必同密码”(零知识);ip_variable 决定 IP 冲突时是拒绝还是接受新分配。

多服务端协调注册:三步握手

配多台服务端时(容灾/负载均衡),所有服务器必须对”谁用哪个 IP”达成一致:

图表(vnt-server-protocol.md)
// vnt-core/src/core/mod.rs:263-272(节选)
let response = if is_multi_server {
    // Multi-server: coordinated pre-registration
    coordinated_registration(&mut ctx.server_managers).await?
} else {
    ctx.server_managers[0].connect_and_reg(RegistrationMode::Normal).await?
};

注册完成后每台服务器一条数据通道:5 秒心跳(顺带携带在线列表版本号)、断线 5 秒退避重连、重连后网段变化则 60 秒退避(全部路由失效需重建)。

三种传输协议与 dynamic://

服务端地址支持前缀选择传输方式(server/transport/config.rs:73-91):

前缀传输特点
(无)或 tcp://TLS over TCP兼容性最好(默认)
quic://QUIC握手快、多路复用
wss://WebSocket over TLS可过只放行 WebSocket 的网络
dynamic://域名DNS TXT 记录发现TXT 里写真实协议与地址——服务端搬家不用改客户端

三种传输统一帧化(LengthDelimitedCodec)后跑同一套 protobuf 协议。在线列表双通道:服务端增量推送(ClientSimpleInfoList{data_version, list[]},data_version 对不上才全量)+ 客户端主动 RPC client_list(返回 name/version/ip/key_sign/online/last_connected_time)。

与其他模块的联系

  • 第 5 篇:key_sign 是服务端唯一的密码知识;中继的包全是密文;
  • 第 6 篇:PunchStart1/2 经服务端转发——服务端是打洞的信使;
  • 第 7 篇:ServerOutbound 按 RTT 选最低延迟的已连服务器发中继包。

常见踩坑

  1. v1 客户端连 v2 服务端——协议不兼容(v2 明示整体重构);
  2. 多服务端只配了一台在配置里却期望容灾——-s 参数可重复,确认全部写上;
  3. dynamic:// 解析失败——检查域名的 TXT 记录格式(支持 udp://quic://tcp://ws://wss:// 前缀)。

随堂练习(带验收标准)

  1. 搭两台服务端(或读 vnts 项目源码),完成协调注册三步。验收:断掉一台后中继照常;
  2. 抓握手包确认传输协议与证书校验模式(skip 时能看到明文证书);
  3. 进阶:配置 dynamic:// 并自建 DNS TXT 记录,验证发现流程。

← 返回文章列表