Add smart ACK provider for WeChat MP replies

Replace fixed ackText with a rule-based AckProvider that picks
response templates by message type and intent (translate, summary,
rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync,
zero I/O, auto-falls back to config.ackText on any error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
john
2026-06-26 15:19:03 +08:00
parent 9ed4fd48d7
commit 9b4a25799f
162 changed files with 17276 additions and 2054 deletions
+34 -29
View File
@@ -1,49 +1,54 @@
# g2.tkmind.cn 负载均衡(Studio + 105
> 2026-06-17 上线。把 g2 H5 的请求按权重分到两台机器:Studio(主)和 105(灰度副)。
> goose **只在 Studio 跑一份**105 是无状态前端孪生,通过 Tailscale 把请求代理回 Studio 的 goosed。
> Goose **只在 103 / Studio 跑**,105 是无状态前端孪生,通过固定公网地址把请求代理回 Studio 的 goosed。
> 2026-06-22 已确认:Studio 上 Goose 不是单实例,而是双实例负载:`18006` 主、`18007` 备用/第二实例;105 仍然不跑 Goose。
## 流量拓扑
```
用户 → 阿里云解析 → 105 服务器公网入口
├─ 转发到本地 Mac 1.6 机器 → 本机 portal 127.0.0.1:8081
├─ 转发到 103 / Studio 服务器 → Studio portal 127.0.0.1:8081
└─ [SSH 正向隧道 127.0.0.1:18080] → 105 portal :8080
105 / 本地主机 两个 portal ── 都连 ──→ 本地 goosed 100.99.38.66:18006唯一实例
发布页文件 ── 都读 ──→ 本地 canonical /Users/john/Project/Memind/MindSpace
105 / Studio 两个 portal ── 都连 ──→ Studio goosed 58.38.22.103:18006
└───Studio goosed 58.38.22.103:18007(备用/第二实例)
发布页文件 ── 都读 ──→ Studio canonical /Users/john/Project/Memind/MindSpace
105 经反向隧道 + rclone 挂载到本地同路径)
```
- **为什么不用旧的 Cloudflare 直连**:当前入口已经迁到阿里云解析,外网流量先到 105,再由 105 转发回本地 Mac 1.6 机器
- **为什么 105 经 SSH 隧道接入**:入口机和 105 之间保持本地 HTTP/SSH 链路,避免把 105 公网地址直接写进上游
- **为什么不用旧的 Cloudflare 直连**:当前入口已经迁到阿里云解析,外网流量先到 105,再由 105 转发到 103 / Studio
- **为什么直接固定公网 IP**:当前服务器互联和部署链路统一使用固定公网地址 `120.26.184.105` / `58.38.22.103`,不再依赖内网地址、域名别名或临时回退链路
## 调灰度比例(最常用
## 105 / 103 联通约束(硬性要求
## 105 联通约束(硬性要求)
**要求:域名只做用户入口;服务器互联、健康检查、部署同步统一走固定公网 IP。**
**要求:105 机器与本机通信必须走 Tailscale 隧道,不允许走外网 IP。**
- 访问、同步、部署 105 一律使用 `ssh105`
- `ssh105``~/.ssh/config` 中绑定为 `100.101.255.32` 并通过 `tailscale nc` 代理;
- 现有脚本默认主机已改为 `root@ssh105`
- 本机对 105 的联通入口是 `127.0.0.1:18080`,不是 `105.tkmind.cn`
- 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 前):
```bash
tailscale --socket /Users/john/Project/ollama/.tailscale/tailscaled.sock status
tailscale --socket /Users/john/Project/ollama/.tailscale/tailscaled.sock ping 100.101.255.32
ssh ssh105 'echo tunnel-ok-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
```
- 禁止:`HostName 120.26.184.105` 直接作为 105 脚本主机。
- 禁止:用 `105.tkmind.cn` 做 API 健康检查或同步链路入口。
- 禁止:把 105 公网 IP 当成业务上游写进 Caddy / goosed 目标;公网 IP 只保留给外部入口或应急 SSH。
- 应急:如果 SSH 别名或本地缓存配置仍残留旧地址,显式设置 `H5_DEPLOY_HOST=root@120.26.184.105`Studio 目标改为 `john@58.38.22.103`
编辑 **本地 Mac 1.6** 上的入口配置,调整流量分配(第一个=本机 :8081,第二个=105 :18080):
## 调灰度比例(最常用)
| 配置 | 本机 | 105 |
编辑 **103 / Studio** 上的入口配置,调整流量分配(第一个=Studio :8081,第二个=105 :18080):
| 配置 | Studio | 105 |
|------|------|-----|
| `weighted_round_robin 19 1` | 95% | 5%(默认上线值) |
| `weighted_round_robin 9 1` | 90% | 10% |
@@ -53,7 +58,7 @@ curl -s http://127.0.0.1:18080/api/status # 应返回 ok
改完**零停机生效**
```bash
ssh 本机入口机
ssh john@58.38.22.103
cd ~/Project/Memind/scripts
caddy validate --config g2-lb.Caddyfile # 可选,先校验
caddy reload --config g2-lb.Caddyfile # 零停机热重载
@@ -74,7 +79,7 @@ caddy reload --config g2-lb.Caddyfile
## 验证 / 观测
每个 g2 响应都带 `X-Memind-Upstream` 头,标记实际命中的上游(`127.0.0.1:8081`=本机`127.0.0.1:18080`=105):
每个 g2 响应都带 `X-Memind-Upstream` 头,标记实际命中的上游(`127.0.0.1:8081`=Studio`127.0.0.1:18080`=105):
```bash
# 打 N 次看分流比例
@@ -84,7 +89,7 @@ for i in $(seq 1 40); do
done | sort | uniq -c
# 看入口反代两个上游健康状态
curl -s http://127.0.0.1:2019/reverse_proxy/upstreams # 在本机入口机上执行
curl -s http://127.0.0.1:2019/reverse_proxy/upstreams # 在 103 / Studio 上执行
```
健康检查会每 10s 打一次各上游的 `/api/status`,连不上或非 200 就自动摘除该上游、流量全转到健康节点;恢复后自动加回。
@@ -93,15 +98,15 @@ curl -s http://127.0.0.1:2019/reverse_proxy/upstreams # 在本机入口机上
| 组件 | 位置 | 作用 |
|------|------|------|
| 入口反代 | 本机入口机 `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` |
| 入口反代 | 103 / Studio `scripts/g2-lb.Caddyfile`LaunchAgent `cn.tkmind.g2-lb`,:8090) | 入口转发 + 健康检查 |
| 正向隧道 | 103 / Studio `scripts/memind-fwd-tunnel.sh`LaunchAgent `cn.tkmind.memind-fwd-tunnel` | Studio `127.0.0.1:18080` → 105 `:8080` |
| 反向隧道 | 103 / 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` | 无状态前端,主 Goose 指向 `https://58.38.22.103:18006`,第二 Goose 指向 `https://58.38.22.103:18007` |
| 105 文件挂载 | 105 systemd `.mount``/mnt/memind-shared`rclone over 反向隧道) | 发布页/工作区共享只读 |
## 关键约束(改动前必读)
- **105 永不跑 goose**。goosed 单实例只在本地 Mac 1.6 机器;session 存本地 SQLite,文件操作也在本地完成。105 只是代理 + serve。
- **105 永不跑 goose**。goosed 只在 103 / Studio;当前是双实例 `18006` / `18007`。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 里的加密设置)。
- 105 必须与 103 / Studio 跑**同一份代码**(用 `sync-to-105.sh` Studio 同步)和**相同的 `TKMIND_SERVER__SECRET_KEY`**(否则连不上 goosed / 解不开共享 RDS 里的加密设置)。
- 调权重只动 `g2-lb.Caddyfile`,不要动 105 的 systemd 单元或 .env。