Extract memind_adm admin server, add local dev tooling, and remove image-generation.
Split platform admin and ops APIs into standalone admin-server.mjs with network guards; simplify billing to RMB token pricing, refactor user auth, and add rsync deploy plus local-test scripts and docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# g2.tkmind.cn 负载均衡(Studio + 105)
|
||||
|
||||
> 2026-06-17 上线。把 g2 H5 的请求按权重分到两台机器:Studio(主)和 105(灰度副)。
|
||||
> goose **只在 Studio 跑一份**,105 是无状态前端孪生,通过 Tailscale 把请求代理回 Studio 的 goosed。
|
||||
|
||||
## 流量拓扑
|
||||
|
||||
```
|
||||
用户 → Cloudflare(橙云) → Tunnel 1d8cda42 → Studio Caddy(:8090, g2-lb)
|
||||
├─ 权重 19 → Studio 本机 portal 127.0.0.1:8081
|
||||
└─ 权重 1 → [SSH正向隧道 127.0.0.1:18080] → 105 portal :8080
|
||||
│
|
||||
105 / Studio 两个 portal ── 都连 ──→ Studio goosed 100.99.38.66:18006(唯一实例)
|
||||
发布页文件 ── 都读 ──→ Studio canonical /Users/john/Project/Memind/MindSpace
|
||||
(105 经反向隧道 + rclone 挂载到本地同路径)
|
||||
```
|
||||
|
||||
- **为什么用 Caddy 加权而不是 Cloudflare LB**:账号未开通 Cloudflare Load Balancing 付费插件(建 pool/monitor 报 `Access Failed`)。Caddy 加权反代免费、可精确控权重,并自带 active 健康检查实现自动摘除。
|
||||
- **为什么 105 经 SSH 隧道接入**:Caddy 一个 `reverse_proxy` 不能混用 http(本地 :8081)和 https(105 公网 :443)上游。用 Studio→105 正向隧道把 105 暴露成本地 HTTP 端口,两个上游就都是本地 http,同协议。
|
||||
|
||||
## 调灰度比例(最常用)
|
||||
|
||||
编辑 **Studio** 上的 `~/Project/Memind/scripts/g2-lb.Caddyfile`,改 `lb_policy weighted_round_robin` 后面两个权重(第一个=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% |
|
||||
|
||||
改完**零停机生效**:
|
||||
|
||||
```bash
|
||||
ssh studio # 或 ssh 100.99.38.66
|
||||
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:
|
||||
|
||||
```bash
|
||||
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`=Studio,`127.0.0.1:18080`=105):
|
||||
|
||||
```bash
|
||||
# 打 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
|
||||
|
||||
# 看 Caddy 两个上游健康状态
|
||||
curl -s http://127.0.0.1:2019/reverse_proxy/upstreams # 在 Studio 上执行
|
||||
```
|
||||
|
||||
active 健康检查会每 10s 打一次各上游的 `/api/status`,连不上或非 200 就自动摘除该上游、流量全转到健康节点;恢复后自动加回。
|
||||
|
||||
## 涉及的组件与配置位置
|
||||
|
||||
| 组件 | 位置 | 作用 |
|
||||
|------|------|------|
|
||||
| g2-lb Caddy | Studio `scripts/g2-lb.Caddyfile`(LaunchAgent `cn.tkmind.g2-lb`,:8090) | 加权反代 + 健康检查 |
|
||||
| 正向隧道 | Studio `scripts/memind-fwd-tunnel.sh`(LaunchAgent `cn.tkmind.memind-fwd-tunnel`) | Studio `127.0.0.1:18080` → 105 `:8080` |
|
||||
| 反向隧道 | Studio `scripts/memind-mac-tunnel.sh`(LaunchAgent `cn.tkmind.memind-tunnel`) | 105 经此挂载 Studio 的 MindSpace 文件 |
|
||||
| 105 portal | 105 systemd `goose-h5`(:8080),`/root/tkmind_go/ui/h5/.env` | 无状态前端,`TKMIND_API_TARGET=https://100.99.38.66:18006` |
|
||||
| 105 文件挂载 | 105 systemd `.mount` → `/mnt/memind-shared`(rclone over 反向隧道) | 发布页/工作区共享只读 |
|
||||
|
||||
## 关键约束(改动前必读)
|
||||
|
||||
- **105 永不跑 goose**。goosed 单实例只在 Studio;session 存 Studio 本地 SQLite,文件操作也在 Studio 本地。105 只是代理 + serve。
|
||||
- 105 的 portal 必须设 `MEMIND_WORKSPACE_MAINTENANCE=0`、`MINDSPACE_AGENT_JOBS_ENABLED=false`——工作区维护守护(缩略图/资产同步 watcher)只该在 Studio 跑,否则 105 对 rclone 挂载树做递归 fs.watch 会占满 libuv 线程池导致 portal 启动卡死。
|
||||
- 105 必须与 Studio 跑**同一份代码**(用 `sync-to-105.sh` 从 Studio 同步)和**相同的 `TKMIND_SERVER__SECRET_KEY`**(否则连不上 goosed / 解不开共享 RDS 里的加密设置)。
|
||||
- 调权重只动 `g2-lb.Caddyfile`,不要动 105 的 systemd 单元或 .env。
|
||||
@@ -0,0 +1,32 @@
|
||||
# 本地开发
|
||||
|
||||
`pnpm dev` 启动后,用 **127.0.0.1 + 端口** 访问:
|
||||
|
||||
| 服务 | 地址 |
|
||||
|------|------|
|
||||
| MindSpace H5 | http://127.0.0.1:5173/?preview=mindspace |
|
||||
| Plaza | http://127.0.0.1:3001/plaza |
|
||||
| Ops 审核后台 | http://127.0.0.1:3002/ops/ |
|
||||
| API / Portal | http://127.0.0.1:8081 |
|
||||
| memind_adm | http://127.0.0.1:8082 |
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
cp .env.example .env
|
||||
PLAZA_APP_DIR=/path/to/plaza pnpm dev
|
||||
pnpm open:local-test # 浏览器打开 H5
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
| 变量 | 默认 | 说明 |
|
||||
|------|------|------|
|
||||
| `H5_PORT` | 8081 | Portal / API |
|
||||
| `VITE_PORT` | 5173 | MindSpace 前端 |
|
||||
| `PLAZA_PORT` | 3001 | Plaza |
|
||||
| `OPS_PORT` | 3002 | Ops SPA |
|
||||
| `ADMIN_PORT` | 8082 | memind_adm |
|
||||
| `H5_PUBLIC_BASE_URL` | http://127.0.0.1:5173 | 公开链接基址 |
|
||||
| `PLAZA_APP_DIR` | ../tkmind_go/ui/plaza | Plaza 源码路径 |
|
||||
|
||||
Plaza 公网部署见 [plaza-local.md](./plaza-local.md)。
|
||||
Reference in New Issue
Block a user