Files
memind/docs/g2-load-balancing.md

5.9 KiB
Raw Permalink Blame History

g2.tkmind.cn 负载均衡(Studio + 105

2026-06-17 上线。把 g2 H5 的请求按权重分到两台机器:Studio(主)和 105(灰度副)。 Goose 只在 103 / Studio 跑,105 是无状态前端孪生,通过固定公网地址把请求代理回 Studio 的 goosed。 2026-06-22 已确认:Studio 上 Goose 不是单实例,而是双实例负载:18006 主、18007 备用/第二实例;105 仍然不跑 Goose。

流量拓扑

用户 → 阿里云解析 → 105 服务器公网入口
                         ├─ 转发到 103 / Studio 服务器 → Studio portal 127.0.0.1:8081
                         └─ [SSH 正向隧道 127.0.0.1:18080] → 105 portal :8080
                                                                                                   │
                       105 / Studio 两个 portal ── 都连 ──→ Studio goosed 58.38.22.103:18006(主)
                                                  └────→ Studio goosed 58.38.22.103:18007(备用/第二实例)
                       MindSpace 服务 ──→ Studio canonical /Users/john/MindSpace (:8082)
                       旧发布页目录 ──兼容/存量──→ /Users/john/Project/Memind/MindSpace
  • 为什么不用旧的 Cloudflare 直连:当前入口已经迁到阿里云解析,外网流量先到 105,再由 105 转发到 103 / Studio。
  • 为什么直接固定公网 IP:当前服务器互联和部署链路统一使用固定公网地址 120.26.184.105 / 58.38.22.103,不再依赖内网地址、域名别名或临时回退链路。

105 / 103 联通约束(硬性要求)

要求:域名只做用户入口;服务器互联、健康检查、部署同步统一走固定公网 IP。

  • 105 运维地址:120.26.184.105
  • 103 / Studio 运维地址:58.38.22.103
  • 如果 SSH 别名未更新,直接写 root@120.26.184.105 / john@58.38.22.103
  • Studio / goosed 目标直接写 58.38.22.103,不要写 g2.tkmind.cn 或 105 域名。
  • Studio 对 105 的联通入口是 127.0.0.1:18080,不是 105.tkmind.cn

快速自检(每次操作 105 前):

ping -c 1 120.26.184.105
ping -c 1 58.38.22.103
ssh root@120.26.184.105 'echo ssh-ok-105'
ssh john@58.38.22.103 'echo ssh-ok-103'
curl -s http://127.0.0.1:18080/api/status   # 应返回 ok
  • 禁止:用 105.tkmind.cn 做 API 健康检查或同步链路入口。
  • 禁止:把 105 公网 IP 当成业务上游写进 Caddy / goosed 目标;公网 IP 只保留给外部入口或应急 SSH。
  • 应急:如果 SSH 别名或本地缓存配置仍残留旧地址,显式设置 H5_DEPLOY_HOST=root@120.26.184.105Studio 目标改为 john@58.38.22.103

调灰度比例(最常用)

编辑 103 / Studio 上的入口配置,调整流量分配(第一个=Studio :8081,第二个=105 :18080):

配置 Studio 105
weighted_round_robin 19 1 95% 5%(默认上线值)
weighted_round_robin 9 1 90% 10%
weighted_round_robin 4 1 80% 20%
weighted_round_robin 1 1 50% 50%

改完零停机生效

ssh john@58.38.22.103
cd ~/Project/Memind/scripts
caddy validate --config g2-lb.Caddyfile   # 可选,先校验
caddy reload  --config g2-lb.Caddyfile     # 零停机热重载

caddy 路径若不在 PATH:用 /opt/homebrew/bin/caddy

一键回滚(把流量全部收回 Studio)

to 那行的 127.0.0.1:18080 删掉(只留 127.0.0.1:8081),或直接恢复备份,然后 reload:

cd ~/Project/Memind/scripts
ls g2-lb.Caddyfile.bak-*          # 找最近备份
cp g2-lb.Caddyfile.bak-XXXX g2-lb.Caddyfile
caddy reload --config g2-lb.Caddyfile

验证 / 观测

每个 g2 响应都带 X-Memind-Upstream 头,标记实际命中的上游(127.0.0.1:8081=Studio127.0.0.1:18080=105):

# 打 N 次看分流比例
for i in $(seq 1 40); do
  curl -s -D - -o /dev/null https://g2.tkmind.cn/api/status \
    | grep -i x-memind-upstream | awk '{print $2}' | tr -d '\r'
done | sort | uniq -c

# 看入口反代两个上游健康状态
curl -s http://127.0.0.1:2019/reverse_proxy/upstreams   # 在 103 / Studio 上执行

健康检查会每 10s 打一次各上游的 /api/status,连不上或非 200 就自动摘除该上游、流量全转到健康节点;恢复后自动加回。

涉及的组件与配置位置

组件 位置 作用
入口反代 103 / Studio scripts/g2-lb.CaddyfileLaunchAgent cn.tkmind.g2-lb:8090 入口转发 + 健康检查
正向隧道 103 / Studio scripts/memind-fwd-tunnel.shLaunchAgent cn.tkmind.memind-fwd-tunnel Studio 127.0.0.1:18080 → 105 :8080
反向隧道 103 / Studio scripts/memind-mac-tunnel.shLaunchAgent cn.tkmind.memind-tunnel 105 经此挂载 Studio MindSpace 文件
105 portal 105 systemd goose-h5:8080),/root/tkmind_go/ui/h5/.env 无状态前端,主 Goose 指向 https://58.38.22.103:18006,第二 Goose 指向 https://58.38.22.103:18007
105 文件挂载 105 systemd .mount/mnt/memind-sharedrclone over 反向隧道) 发布页/工作区共享只读

关键约束(改动前必读)

  • 105 永不跑 goose。goosed 只在 103 / Studio;当前是双实例 18006 / 18007。105 只是代理 + serve。
  • 105 的 portal 必须设 MEMIND_WORKSPACE_MAINTENANCE=0MINDSPACE_AGENT_JOBS_ENABLED=false——工作区维护守护(缩略图/资产同步 watcher)只该在本地跑,否则 105 对 rclone 挂载树做递归 fs.watch 会占满 libuv 线程池导致 portal 启动卡死。
  • 105 必须与 103 / Studio 跑同一份代码(用 sync-to-105.sh 从 Studio 同步)和相同的 TKMIND_SERVER__SECRET_KEY(否则连不上 goosed / 解不开共享 RDS 里的加密设置)。
  • 调权重只动 g2-lb.Caddyfile,不要动 105 的 systemd 单元或 .env。