Skip to content

Repository files navigation

TeamViewRelay Backend

TeamViewRelay 的 Rust 后端服务。它接收 Minecraft 客户端上报的数据,按房间聚合状态,并广播给游戏内客户端和网页地图端。

功能

  • 玩家、实体、路标、战局区块及玩家标记的状态聚合
  • 玩家端与外部全局上报源的来源仲裁
  • 在线 Tab 状态、离线位置和 Tab History
  • 基于 Protobuf 的全量快照、增量广播和版本兼容
  • 内置 Vue 管理页面、实时指标、审计和 SQLite 持久化
  • HTTP、SSE、Minecraft 与 Web Map WebSocket 的可信代理真实 IP 解析

相关组件:

项目文档:

快速启动

推荐直接使用 Docker Compose:

export TEAMVIEWER_ADMIN_USERNAME=admin
export TEAMVIEWER_ADMIN_PASSWORD=please-change-me
docker compose up -d
curl --fail http://127.0.0.1:8765/health

默认端点:

  • ws://127.0.0.1:8765/mc-client:Minecraft 客户端
  • ws://127.0.0.1:8765/web-map/ws:网页地图
  • http://127.0.0.1:8765/admin:管理页面
  • http://127.0.0.1:8765/health:健康检查
  • http://127.0.0.1:8765/snapshot:状态快照

/playeresp/adminws 仅作为旧客户端兼容入口保留。

协议兼容矩阵

服务端当前协议为 0.8.0,最低支持 0.6.1。握手要求客户端和服务端声明的 [minimum_compatible_network_protocol_version, network_protocol_version] 区间相交;实际功能按双方都支持的最高版本选择。

兼容策略集中在 src/protocol_compat.rs,领域状态始终使用当前模型,只有连接边界上的 handshake、snapshot、patch、digest 和入站报告会经过 profile 投影。管理后台会显示每个在线连接的 epoch 和命中的规则。

客户端 epoch 活跃兼容规则数 主要适配
0.6.1 7 移除 battle mode、角色、last seen、来源元数据和 Tab History;clear-fields 回退;legacy digest
0.6.2 6 角色、last seen、来源元数据、clear-fields、Tab History、legacy digest
0.6.3 5 last seen、来源元数据、clear-fields、Tab History、legacy digest
0.6.4 4 来源元数据、clear-fields、Tab History、legacy digest
0.6.5 2 Tab History、legacy digest
0.7.0 1 legacy battle chunk digest
0.7.1 0 保留实时状态、Tab 历史,不开放关系查询
0.8.0 0 当前合同,支持外部目录和关系查询

以后升级协议时,必须同时:新增或更新 epoch 能力、为真实投影登记稳定规则 ID、补边界与摘要向量测试,并确认管理后台能枚举新规则。 提高最低兼容版本时,应在同一提交中删除已不可触发的 epoch、规则和测试。

Docker

构建当前源码:

docker build -t teamviewrelay-backend:local .

已发布镜像:

professornuo/teamviewrelay-rust:v1.2.0-alpha.3-proto0.8.0

docker-compose.yml 默认使用该版本,并将 SQLite 数据目录挂载到宿主机的 ./data-rust

内存与 CPU Debug 镜像

Debug 监控只在 memory-debug Cargo feature 中存在,普通 release 不包含 profiler、采样任务或 Debug API。使用独立 compose overlay 构建并部署:

docker compose -f docker-compose.yml -f docker-compose.memory-debug.yml up -d --build
docker compose logs -f backend

它对应镜像 tag v1.2.0-alpha.2-memory-debug-proto0.8.0,每 10 秒把资源快照写入 ./data-rust/memory-debug/samples-YYYY-MM-DD.jsonl,heap 原始 dump、pprof、手动 CPU pprof 和 SVG 火焰图写入 ./data-rust/memory-debug/profiles/。首次 heap profile 默认在启动 2 分钟后生成;内存相对 上次 profile 增长 8 MiB 时会自动追加抓取。heap 的符号解析由一次性子进程完成,解析缓存不会进入 服务进程 RSS。采样文件持续记录进程、线程和 cgroup CPU,默认不会自动启动进程内 CPU profiler。

登录管理页后可使用以下鉴权接口:

  • GET /admin/api/debug/resources/current:最近一次资源快照与 profiler 状态。
  • GET /admin/api/debug/resources/profiles:可下载的 profile 列表。
  • POST /admin/api/debug/resources/profiles/cpu:手动抓取 30 秒 CPU profile。
  • POST /admin/api/debug/resources/profiles/heap:手动抓取 heap profile。
  • GET /admin/api/debug/resources/profiles/{filename}:下载 profile。

本机直接构建等价二进制时使用:

RUSTFLAGS="-C force-frame-pointers=yes" \
  cargo build --profile memory-debug --features memory-debug

常用环境变量:

变量 默认值 说明
TEAMVIEWER_PORT 8765 服务监听端口
TEAMVIEWER_DB_PATH ./data/teamviewer-admin.db SQLite 数据库路径
TEAMVIEWER_ADMIN_USERNAME admin 管理员用户名
TEAMVIEWER_ADMIN_PASSWORD admin 管理员密码,生产环境必须覆盖
TEAMVIEWER_ADMIN_SESSION_TTL_SEC 43200 管理会话有效期
TEAMVIEWER_WT_ENABLED false 是否启用 WebTransport/QUIC;启用需显式配置证书
TEAMVIEWER_WT_BIND 0.0.0.0:8766 QUIC UDP 监听地址
TEAMVIEWER_WT_CERT_PATH PEM fullchain 路径;生产使用 Let’s Encrypt fullchain.pem
TEAMVIEWER_WT_KEY_PATH PEM private key 路径;生产使用 Let’s Encrypt privkey.pem
TEAMVIEWER_WT_IDENTITIES 多证书 JSON 数组,设置后整体覆盖 CERT_PATH/KEY_PATH 与 TOML 证书配置
TEAMVIEWER_WT_POLL_INTERVAL_SEC 300 证书文件检查间隔,范围 30–86400
TEAMVIEWER_WT_RENEW_WINDOW_SEC 604800 到期提前拒绝窗口,范围 1–30 天
TEAMVIEWER_TRUST_PROXY_HEADERS false 是否读取可信反代转发的真实 IP
TEAMVIEWER_TRUSTED_PROXY_CIDRS 本机与 Docker 私网段 可被信任的直连反代地址段
RUST_LOG info Rust 日志过滤规则
TZ 系统时区 管理统计使用的时区

Debug overlay 还支持 TEAMVIEWER_DEBUG_SAMPLE_INTERVAL_SECTEAMVIEWER_DEBUG_AUTO_CPU_PROFILETEAMVIEWER_DEBUG_CPU_TRIGGER_PERCENTTEAMVIEWER_DEBUG_CPU_PROFILE_SECTEAMVIEWER_DEBUG_MEMORY_GROWTH_MIBTEAMVIEWER_DEBUG_STARTUP_PROFILE_DELAY_SECTEAMVIEWER_DEBUG_PERIODIC_PROFILE_SECTEAMVIEWER_DEBUG_PROFILE_COOLDOWN_SECTEAMVIEWER_DEBUG_RETENTION_DAYSTEAMVIEWER_DEBUG_MAX_PROFILESTEAMVIEWER_DEBUG_MAX_DISK_MIB。默认保留 7 天采样、48 组 profile,并限制 profile 总量为 512 MiB。 设置 TEAMVIEWER_DEBUG_AUTO_CPU_PROFILE=true 才会恢复启动、高 CPU 和周期 CPU profile。进程内 CPU profile 会显著增加常驻符号缓存并短暂干扰业务吞吐;诊断长期内存增长时应保持默认关闭,只在内存样本 收集完成后手动触发。

反向代理与真实 IP

启用可信代理头时,后端只会在 TCP 直连来源属于 TEAMVIEWER_TRUSTED_PROXY_CIDRS 时读取代理头,并按以下优先级选择第一个合法 IP:

  1. CF-Connecting-IP
  2. X-Real-IP
  3. X-Forwarded-For

示例:

export TEAMVIEWER_TRUST_PROXY_HEADERS=true
export TEAMVIEWER_TRUSTED_PROXY_CIDRS=127.0.0.1/32,::1/128,172.16.0.0/12
docker compose up -d

OpenResty / Nginx 示例位于 deploy/openresty-teamviewer.conf.example

WebTransport 与 QUIC

WebTransport 默认关闭。启用时必须提供 PEM 证书和私钥,后端只热检测并替换证书,不内嵌 ACME。UDP 端口必须直连或在容器/防火墙上显式映射;Nginx 与 OpenResty 不能按普通 HTTP 反代 WebTransport。

单证书(向后兼容):

export TEAMVIEWER_WT_ENABLED=true
export TEAMVIEWER_WT_BIND=0.0.0.0:8766
export TEAMVIEWER_WT_CERT_PATH=/app/certs/fullchain.pem
export TEAMVIEWER_WT_KEY_PATH=/app/certs/privkey.pem

多证书(域名证书 + IP 证书等):通过 TEAMVIEWER_WT_IDENTITIES(JSON 数组)或 TOML identities 配置,最多 16 张:

export TEAMVIEWER_WT_IDENTITIES='[
  {"certPath": "/app/certs/fullchain.pem", "keyPath": "/app/certs/privkey.pem"},
  {"certPath": "/app/certs/ip.crt.pem", "keyPath": "/app/certs/ip.key.pem", "default": true}
]'

优先级:TEAMVIEWER_WT_IDENTITIES > TEAMVIEWER_WT_CERT_PATH/KEY_PATH > TOML identities > TOML certPath/keyPath;环境变量任一形式存在时整体替换 TOML 证书配置。

每个 TLS 握手按以下顺序选证书:

  1. SNI 精确命中某张证书的 DNS SAN(大小写不敏感);
  2. SNI 泛域名命中(仅最左单标签 *.example.com);
  3. default = true 标记的证书;
  4. 第一张含 IP SAN 的证书;
  5. 第一张证书兜底。

浏览器按 IP 直连时因 RFC 6066 不发送 SNI,因此需要一条 default 标记或 IP SAN 证书承接。 SNI 未命中任意证书时回退到默认证书并记录 warn 日志。

热轮换按证书独立进行:单张文件读取或解析失败只影响该张(保留旧证书,其余正常轮换);新证书 有效期落入 renewWindowSec 内则拒绝替换并保持旧证书,下个轮询周期复查。

浏览器入口为 https://host:8766/web-map/wt。WS 路径保持不变;Java mod 第一版继续使用 WebSocket。证书更新成功只影响新 QUIC 连接,已有连接保留旧 TLS 配置并按客户端重连收敛。

源码开发

环境要求:

  • Rust 1.94+
  • Node.js 24+ 与 pnpm(仅管理前端)
  • 已初始化的协议 submodule

初始化并验证:

git submodule update --init --recursive

cd admin-ui
corepack enable
pnpm install --frozen-lockfile
pnpm test
pnpm build
cd ..

cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
cargo run --release

管理前端开发服务器:

cd admin-ui
pnpm dev

Vite 会把管理 API、SSE 和管理页请求代理到 127.0.0.1:8765

管理页面按“概览 / 流量 / 活跃指标 / 数据管理 / 审计日志”分区。在“数据管理”中可按房间清理压测或废弃数据:房间必须离线,并需要再次输入完整房间名确认。清理范围包括该房间的审计、日/小时活跃行、Tab History、Last Seen 缓存和不再被其他房间引用的身份映射;全局聚合的历史流量无法归属到具体房间,因此始终保留。

压力测试

scripts/load_test_live.py 是独立的黑盒协议压测工具,不导入或启动任何 Python 后端。运行时会根据锁定的协议 submodule 在临时目录生成 Python binding;因此需要安装 uv 并先初始化 submodule。

对当前 Rust 版本执行远程压测:

git submodule update --init --recursive

uv run python scripts/load_test_live.py \
  --url http://192.0.2.10:2052/mc \
  --stages 10,20,40 \
  --stage-duration 300 \
  --report-hz 10 \
  --allow-remote \
  --expected-build team-view-relay-rust-v1.2.0-alpha.3-proto0.8.0

--expected-build 必须与目标 /health 返回的 buildVersion 完全一致,而不是 Docker tag。可先检查:

curl http://192.0.2.10:2052/mc/health

默认压测房间为 load-benchmark-v3,脚本拒绝使用 default 房间。每档用户数会创建等量的 Mod 上报端和 Web 消费端,外加一个全局上报源,所以 10,20,40 分别对应 21、41、81 条 WebSocket 连接。

运行配置

状态超时、广播频率、拥塞降级、Tab History 和同服过滤配置位于:

config/server_state_config.toml

该文件通过 include_str! 编译进二进制,修改后需要重新构建后端。

战区历史默认保留 7,200 秒,并通过 battleChunkCacheMaxEntries = 65536 限制每个房间的最大 区块数。缓存使用无损值共享;达到时间或数量任一上限时淘汰最老区块。

项目结构

.
├── src/                         Rust 后端源码与测试
├── migrations/                  SQLite migration
├── config/                      服务端状态配置
├── admin-ui/                    Vue 管理页面及 Vitest 测试
├── deploy/                      反向代理配置示例
├── docs/                        设计与演进文档
├── scripts/                     独立黑盒压测工具
├── third_party/
│   └── TeamViewRelay-Protocol/  commit 锁定的共享协议 submodule
├── Cargo.toml
├── Dockerfile
└── docker-compose.yml

协议依赖

共享协议源固定来自:

third_party/TeamViewRelay-Protocol/proto/teamviewer/v1/teamviewer.proto

仓库不会复制或手改 .proto。Rust binding 由 build.rs 在 Cargo 构建时生成到 OUT_DIR,不提交生成产物。

协议升级必须显式锁定 tag 或 commit:

git -C third_party/TeamViewRelay-Protocol fetch --tags
git -C third_party/TeamViewRelay-Protocol checkout proto/vX.Y.Z
git add third_party/TeamViewRelay-Protocol

cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets

About

后端代码

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages