Add attachment text extraction, auto web news skill, and chat/voice UI updates.
Simplify asset upload temp paths, refresh deploy docs for Aliyun DNS topology, and ship MindSpace content-scan and auth improvements. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+21
-21
@@ -6,17 +6,17 @@
|
||||
## 流量拓扑
|
||||
|
||||
```
|
||||
用户 → 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 服务器公网入口
|
||||
├─ 转发到本地 Mac 1.6 机器 → 本机 portal 127.0.0.1:8081
|
||||
└─ [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 / 本地主机 两个 portal ── 都连 ──→ 本地 goosed 100.99.38.66:18006(唯一实例)
|
||||
发布页文件 ── 都读 ──→ 本地 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,同协议。
|
||||
- **为什么不用旧的 Cloudflare 直连**:当前入口已经迁到阿里云解析,外网流量先到 105,再由 105 转发回本地 Mac 1.6 机器。
|
||||
- **为什么 105 经 SSH 隧道接入**:入口机和 105 之间保持本地 HTTP/SSH 链路,避免把 105 公网地址直接写进上游。
|
||||
|
||||
## 调灰度比例(最常用)
|
||||
|
||||
@@ -41,10 +41,10 @@ curl -s http://127.0.0.1:18080/api/status # 应返回 ok
|
||||
- 禁止:`HostName 120.26.184.105` 直接作为 105 脚本主机。
|
||||
- 禁止:用 `105.tkmind.cn` 做 API 健康检查或同步链路入口。
|
||||
|
||||
编辑 **Studio** 上的 `~/Project/Memind/scripts/g2-lb.Caddyfile`,改 `lb_policy weighted_round_robin` 后面两个权重(第一个=Studio :8081,第二个=105 :18080):
|
||||
编辑 **本地 Mac 1.6** 上的入口配置,调整流量分配(第一个=本机 :8081,第二个=105 :18080):
|
||||
|
||||
| 配置 | Studio | 105 |
|
||||
|------|--------|-----|
|
||||
| 配置 | 本机 | 105 |
|
||||
|------|------|-----|
|
||||
| `weighted_round_robin 19 1` | 95% | 5%(默认上线值) |
|
||||
| `weighted_round_robin 9 1` | 90% | 10% |
|
||||
| `weighted_round_robin 4 1` | 80% | 20% |
|
||||
@@ -53,7 +53,7 @@ curl -s http://127.0.0.1:18080/api/status # 应返回 ok
|
||||
改完**零停机生效**:
|
||||
|
||||
```bash
|
||||
ssh studio # 或 ssh 100.99.38.66
|
||||
ssh 本机入口机
|
||||
cd ~/Project/Memind/scripts
|
||||
caddy validate --config g2-lb.Caddyfile # 可选,先校验
|
||||
caddy reload --config g2-lb.Caddyfile # 零停机热重载
|
||||
@@ -74,7 +74,7 @@ caddy reload --config g2-lb.Caddyfile
|
||||
|
||||
## 验证 / 观测
|
||||
|
||||
每个 g2 响应都带 `X-Memind-Upstream` 头,标记实际命中的上游(`127.0.0.1:8081`=Studio,`127.0.0.1:18080`=105):
|
||||
每个 g2 响应都带 `X-Memind-Upstream` 头,标记实际命中的上游(`127.0.0.1:8081`=本机,`127.0.0.1:18080`=105):
|
||||
|
||||
```bash
|
||||
# 打 N 次看分流比例
|
||||
@@ -83,25 +83,25 @@ for i in $(seq 1 40); do
|
||||
| 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 上执行
|
||||
# 看入口反代两个上游健康状态
|
||||
curl -s http://127.0.0.1:2019/reverse_proxy/upstreams # 在本机入口机上执行
|
||||
```
|
||||
|
||||
active 健康检查会每 10s 打一次各上游的 `/api/status`,连不上或非 200 就自动摘除该上游、流量全转到健康节点;恢复后自动加回。
|
||||
健康检查会每 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 文件 |
|
||||
| 入口反代 | 本机入口机 `scripts/g2-lb.Caddyfile`(LaunchAgent `cn.tkmind.g2-lb`,:8090) | 入口转发 + 健康检查 |
|
||||
| 正向隧道 | 本机入口机 `scripts/memind-fwd-tunnel.sh`(LaunchAgent `cn.tkmind.memind-fwd-tunnel`) | 本机 `127.0.0.1:18080` → 105 `:8080` |
|
||||
| 反向隧道 | 本机入口机 `scripts/memind-mac-tunnel.sh`(LaunchAgent `cn.tkmind.memind-tunnel`) | 105 经此挂载本地 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 里的加密设置)。
|
||||
- **105 永不跑 goose**。goosed 单实例只在本地 Mac 1.6 机器;session 存本地 SQLite,文件操作也在本地完成。105 只是代理 + serve。
|
||||
- 105 的 portal 必须设 `MEMIND_WORKSPACE_MAINTENANCE=0`、`MINDSPACE_AGENT_JOBS_ENABLED=false`——工作区维护守护(缩略图/资产同步 watcher)只该在本地跑,否则 105 对 rclone 挂载树做递归 fs.watch 会占满 libuv 线程池导致 portal 启动卡死。
|
||||
- 105 必须与本地主机跑**同一份代码**(用 `sync-to-105.sh` 从主机同步)和**相同的 `TKMIND_SERVER__SECRET_KEY`**(否则连不上 goosed / 解不开共享 RDS 里的加密设置)。
|
||||
- 调权重只动 `g2-lb.Caddyfile`,不要动 105 的 systemd 单元或 .env。
|
||||
|
||||
+16
-16
@@ -8,20 +8,20 @@
|
||||
用户访问 `https://g2.tkmind.cn/` 的流量路径:
|
||||
|
||||
```text
|
||||
Cloudflare(橙云)
|
||||
→ Cloudflare Tunnel
|
||||
→ Studio Caddy(:8090,g2 负载均衡)
|
||||
├─ 权重 19 → Studio Portal(127.0.0.1:8081) ← 主流量
|
||||
└─ 权重 1 → 105 Portal(经隧道 127.0.0.1:18080 → :8080) ← 灰度副机
|
||||
阿里云解析(DNS)
|
||||
→ 105 服务器(公网入口 / 反代)
|
||||
→ 本地 Mac 1.6 机器(主服务)
|
||||
├─ 主流量 → 本地 Portal(127.0.0.1:8081)
|
||||
└─ 备用/灰度 → 105 Portal(经隧道 127.0.0.1:18080 → :8080)
|
||||
```
|
||||
|
||||
两台 Portal 都是 **无状态前端**,共用 Studio 上的 goosed 与 MindSpace 数据目录。
|
||||
|
||||
| 角色 | 机器 | 代码目录 | 服务 | 重启方式 |
|
||||
|------|------|----------|------|----------|
|
||||
| 生产主 | Studio Mac(`100.99.38.66`) | `/Users/john/Project/Memind` | Portal `:8081`、Plaza `:3001` | `launchctl kickstart` |
|
||||
| 生产主 | 本地 Mac 1.6 机器 | `/Users/john/Project/Memind` | Portal `:8081`、Plaza `:3001` | `launchctl kickstart` |
|
||||
| 入口转发 | 105 服务器 | 入口转发配置 | 反代 `:80/:443` | 阿里云解析切换后生效 |
|
||||
| 灰度副 | 105(经 Tailscale `ssh105`) | `/root/tkmind_go/ui/h5` | `goose-h5` `:8080` | `systemctl restart goose-h5` |
|
||||
| 负载均衡 | Studio | `scripts/g2-lb.Caddyfile` | Caddy `:8090` | 改权重后 `caddy reload` |
|
||||
|
||||
更详细的流量与灰度比例说明见 [g2 负载均衡](./g2-load-balancing.md)。
|
||||
|
||||
@@ -57,7 +57,7 @@ cd /path/to/your/memind-repo # 开发完成、已自测的目录
|
||||
4. rsync 代码 → Studio 生产目录
|
||||
5. rsync 后校验(`.env` 未变、MindSpace 未减少、patch 仍在)
|
||||
6. Studio 上 `npm install` + `npm run build`
|
||||
7. 重启 Studio Portal → Plaza,并做健康检查
|
||||
7. 重启本地 Mac 1.6 Portal → Plaza,并做健康检查
|
||||
8. 经 Studio 触发 `scripts/sync-to-105.sh`,同步并重启 105
|
||||
|
||||
## 4. 发布前检查清单
|
||||
@@ -81,7 +81,7 @@ pnpm test # 建议跑;涉及核心逻辑时必跑
|
||||
### 4.2 生产在线(只读)
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:8081/api/status # Studio Portal,期望 ok
|
||||
curl -s http://127.0.0.1:8081/api/status # 本地 Portal,期望 ok
|
||||
curl -s http://127.0.0.1:18080/api/status # 105 隧道,期望 ok
|
||||
```
|
||||
|
||||
@@ -110,8 +110,8 @@ ssh ssh105 'echo tunnel-ok-105'
|
||||
| 参数 | 作用 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| `--dry-run` | 只预览 diff,不改远端 | **每次正式发布前必做** |
|
||||
| `--only-100` | 只更新 Studio,不推 105 | 先让 95% 主流量生效,105 稍后 |
|
||||
| `--only-105` | 只触发 Studio→105 同步 | Studio 已是最新,只补 105 |
|
||||
| `--only-100` | 只更新本地主机,不推 105 | 先让主流量生效,105 稍后 |
|
||||
| `--only-105` | 只触发本地主机→105 同步 | 主机已是最新,只补 105 |
|
||||
| `--skip-build` | 跳过远端 `npm run build` | 纯后端改动且确认 dist 无需更新 |
|
||||
| `--no-restart` | 只同步代码,不重启服务 | 分批发布;需自行重启 |
|
||||
| `--yes` / `-y` | 跳过交互确认 | 自动化或你已看过 dry-run |
|
||||
@@ -169,11 +169,11 @@ package.json 中的 `pnpm deploy:105` 等价于本地执行 `bash scripts/sync-t
|
||||
| 阶段 | 用户可见影响 |
|
||||
|------|----------------|
|
||||
| rsync + npm install + build | 无(旧进程仍在跑) |
|
||||
| Studio Portal 重启 | **8081 短暂不可用**,约 10~40 秒;g2 主流量(约 95%)可能短暂 502 |
|
||||
| 本地 Portal 重启 | **8081 短暂不可用**,约 10~40 秒;主流量可能短暂 502 |
|
||||
| 105 goose-h5 重启 | **灰度流量(约 5%)** 短暂不可用 |
|
||||
| Plaza 重启 | plaza.tkmind.cn 可能短暂不可用;与 g2 主聊天无关 |
|
||||
|
||||
Caddy 会对不健康上游做 active health check,105 重启期间可能暂时从池中摘除。
|
||||
入口反代会对不健康上游做健康检查,105 重启期间可能暂时从池中摘除。
|
||||
|
||||
## 8. 发布后验证
|
||||
|
||||
@@ -189,7 +189,7 @@ curl -s https://g2.tkmind.cn/api/status
|
||||
|
||||
g2 响应头 `X-Memind-Upstream`:
|
||||
|
||||
- `127.0.0.1:8081` → Studio
|
||||
- `127.0.0.1:8081` → 本地 Mac 1.6 机器
|
||||
- `127.0.0.1:18080` → 105
|
||||
|
||||
```bash
|
||||
@@ -208,7 +208,7 @@ curl -s -D - -o /dev/null https://g2.tkmind.cn/api/status | grep -i x-memind-ups
|
||||
### 8.4 日志
|
||||
|
||||
```bash
|
||||
# Studio Portal
|
||||
# 本地 Portal
|
||||
tail -f ~/Library/Logs/memind-portal.log
|
||||
|
||||
# Studio Plaza
|
||||
@@ -223,7 +223,7 @@ ssh ssh105 'journalctl -u goose-h5 -n 50 --no-pager'
|
||||
项目没有一键回滚脚本,常见做法:
|
||||
|
||||
1. **代码回滚:** 在本地 git 回到上一个 good commit,`./rsync_to_server.sh` 再发一版
|
||||
2. **仅 Studio:** 若 105 有问题,可临时把 g2 权重调到 100% Studio(见 [g2-load-balancing.md](./g2-load-balancing.md))
|
||||
2. **仅本地主机:** 若 105 有问题,可临时把流量全部收回主机(见 [g2-load-balancing.md](./g2-load-balancing.md))
|
||||
3. **紧急恢复 Portal:** 若 8081 挂了,见 [隔离规程 · 事故恢复](./service-isolation-runbook.md#事故恢复最小步骤)
|
||||
|
||||
发布前建议打 tag 或记录当前 commit,便于回滚:
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
| 环境 | 目录 | 用途 | 端口 |
|
||||
|------|------|------|------|
|
||||
| 生产 | `/Users/john/Project/Memind` | `g2.tkmind.cn` 当前在线服务 | `8081` |
|
||||
| 生产 | `/Users/john/Project/Memind` | `g2.tkmind.cn` 当前在线服务(阿里云解析 → 105 → 本地 Mac 1.6) | `8081` |
|
||||
| 生产 Plaza | `/Users/john/Project/Memind` + Plaza | `plaza.tkmind.cn` 当前在线服务 | `3001` |
|
||||
| 生产 Caddy | `/Users/john/Project/Memind/scripts/g2-lb.Caddyfile` | Cloudflare Tunnel 回源入口 | `8090` |
|
||||
| 生产入口 | `/Users/john/Project/Memind/scripts/g2-lb.Caddyfile` | 105 转发入口 / 反代配置 | `8090` |
|
||||
| 测试 Portal | `/Users/john/Project/test/Memind` | 开发预览 API / Portal | `18081` |
|
||||
| 测试 Vite | `/Users/john/Project/test/Memind` | 开发预览前端 | `15173` |
|
||||
| 测试 Admin | `/Users/john/Project/test/Memind` | 开发预览后台 | `18082` |
|
||||
@@ -197,7 +197,7 @@ pnpm dev:vite -- --host 127.0.0.1 --port 15173
|
||||
|
||||
## 事故恢复最小步骤
|
||||
|
||||
如果发现 `g2.tkmind.cn` 异常,先检查本机生产:
|
||||
如果发现 `g2.tkmind.cn` 异常,先检查本地主机生产:
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/Memind
|
||||
@@ -205,7 +205,7 @@ lsof -nP -iTCP:8081 -sTCP:LISTEN
|
||||
curl -s http://127.0.0.1:8081/api/status
|
||||
```
|
||||
|
||||
如果 `8081` 没有监听,再恢复生产 Portal:
|
||||
如果 `8081` 没有监听,再恢复本地主机 Portal:
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/Memind
|
||||
@@ -215,7 +215,7 @@ sleep 2
|
||||
curl -s http://127.0.0.1:8081/api/status
|
||||
```
|
||||
|
||||
恢复后再检查 Caddy:
|
||||
恢复后再检查入口反代:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:8090/api/status
|
||||
|
||||
Reference in New Issue
Block a user