118 lines
8.7 KiB
Markdown
118 lines
8.7 KiB
Markdown
# iXserverLoopEnv:模拟闭环测试环境
|
||
|
||
在 FG-W11-ICON-DEV 一台机器上把五个角色跑起来,让一条 IG 消息从入站到第三方回复、再回到 IG 全程走真 HTTP。
|
||
方案与取舍见 iXserver 仓库的 `docs/构建模拟闭环测试环境.html`。
|
||
|
||
| 角色 | 端口 | 来源 |
|
||
| --- | --- | --- |
|
||
| ABP(授权 + 消息模板) | https 44332 | `C:\Projects\HKTBAbp` 发布到 `run\abp` |
|
||
| iXserver API(IIS Express) | 8081,WebSocket 33346 | `C:\Projects\iXserver` 整解决方案编译后拷到 `run\ixserver` |
|
||
| 第三方 chatbot 客户端 | 5056 | `iXserver\Tools\ThirdPartyChatbotTestClient` |
|
||
| IG 后端模拟 | 5070 | `iXserver\Tools\IgMockServer` |
|
||
| SCRM 客服系统模拟 | 5080 | `iXserver\Tools\ScrmMockServer` |
|
||
| 闭环观察台(只读,泳道时序图) | 5090 | `iXserver\Tools\LoopConsole` |
|
||
|
||
所有端口只绑本机。iXserver 的旧接口和 WebSocket **没有鉴权**,绝不能对外开放 8081 / 33346。
|
||
|
||
## 这个仓库装什么
|
||
|
||
只装「环境」:`loop.ps1`、`config\`、`db\`、`tools\`、`scenarios\`、`deployed.json`。
|
||
程序本身不在这里——两个模拟服务的代码在 iXserver 的 `Tools\`(它们模拟的是 iXserver 自己的协议,
|
||
要和协议改动同一个提交);编译产物、日志、上传文件在被忽略的 `run\`。
|
||
|
||
**以 Mac 上的 `~/projects/iXserverLoopEnv` 为准**,用 remote-dev-box 的 `sync.sh` 推到 winbox 的
|
||
`C:\Projects\iXserverLoopEnv`。提交在 Mac 上做,winbox 上只跑。
|
||
|
||
## 第一次
|
||
|
||
```powershell
|
||
.\loop.ps1 reset-abp -Init # iCONAbpFX 拷完后:换 setsail secret 与 admin 密码,留底
|
||
.\loop.ps1 deploy # 编译 iXserver 整解决方案 + 发布 ABP(慢)
|
||
.\loop.ps1 reset # 建 iXserverLoop:EDMX 建表 → FeatureTest 种子 → loop_patch,留底
|
||
.\loop.ps1 up
|
||
```
|
||
|
||
之后日常:
|
||
|
||
```powershell
|
||
.\loop.ps1 status
|
||
.\loop.ps1 deploy -Only ixserver # 改了 iXserver 代码
|
||
.\loop.ps1 deploy -Only ixserver -ConfigOnly # 只改了 config\ixserver\overrides.psd1
|
||
.\loop.ps1 reset -FromBackup # 库回到干净状态(秒级)
|
||
.\loop.ps1 logs -Only ixserver -Tail 100
|
||
.\loop.ps1 down
|
||
```
|
||
|
||
## 场景
|
||
|
||
`scenarios\` 下每个脚本独立可跑,通过退出 0、失败退出 1 并打印两侧记录。前提是 `up` 后各角色都健康。
|
||
观察台在跑时,每次跑完(通过或失败)都会生成一份**场景报告**:这次的时序图、iXserver 内部步骤、逐步断言、部署版本,
|
||
存成 `run\reports\<开始时间>-<场景>-<PASS|FAIL>.html`(单文件,离线可开,不进 git)。
|
||
`.\loop.ps1 reports` 列出最近的,观察台 <http://127.0.0.1:5090/reports/> 里也能点开。加 `-NoReport` 只断言不出报告(省几秒)。
|
||
新写场景照 S1 / S8 点源 `scenarios\_lib.ps1`:`Start-LoopRun` → 每个断言 `Add-LoopStep` → `Save-LoopReport`。
|
||
|
||
```powershell
|
||
.\scenarios\s1-ig-text-echo.ps1 # IG 文本 → iXserver → 第三方 chatbot echo → IG 收到
|
||
.\scenarios\s2-auth-ip-whitelist.ps1 # IP 白名单:token 端点 + send-txt 经真 IIS 放行 / 拒绝、可信代理的 XFF 规则;临时改 oauth_client 与 Web.config,结束还原,约 2~3 分钟
|
||
.\scenarios\s5-ig-handoff.ps1 # 机器人工单 → SCRM 开工 + 客服上线 → 下一条:echo 在前、问句在后 → 点 Yes → 新人工工单 → 客服回复 → 旧单迟到回复 409 → 下班
|
||
.\scenarios\s8-human-chain.ps1 # SCRM 开工 → 新 IG 用户 → 人工工单推送 → 指派 / 回复 → IG 收到 → 结束 → 下班
|
||
```
|
||
|
||
S5 依赖 `epro_ig_demo` 的 `DisconnectChatbotFlowSetting` 已打开(`db\ixserver\loop_patch.sql` 第 3 节;没 reset 过的库要单独执行那一段),
|
||
问句按钮标题跟 ABP 模板走,模板改过时用 `-YesTitle` 指定。
|
||
|
||
跑的时候开着观察台 <http://127.0.0.1:5090>,每一跳和状态变化会实时画成泳道时序图;`?ticket=<工单号>` 只看一张。
|
||
|
||
`epro_ig_demo` 常开条款同意(`db\ixserver\loop_patch.sql` 第 3 节的 `T_and_C_Setting`):
|
||
新 IG 用户的第一句话会被条款拦下,三个场景都先调 `_lib.ps1` 的 `Complete-LoopTnC` 走完「条款 → 同意 → 选语言 → 问候」。
|
||
staging 的 IG 条款组**缺 Agree 按钮**(漏了 Line 问候里的「Agreement Button (Line IG)」);闭环 ABP 在
|
||
`db\abp\loop_patch.sql` 第 3 节补上了,这一处与 staging 不同。改过这个补丁要 `.\loop.ps1 reset-abp -Init` 重新打并留底。
|
||
|
||
S5 / S8 结束时(失败也一样)会把服务号切回机器人、在线人数归零,所以几个场景先后跑互不影响;要停在人工状态看页面加 `-KeepShift`。
|
||
|
||
从 Mac 看几个页面用 SSH 本地端口转发:
|
||
|
||
```bash
|
||
ssh -N -L 5056:127.0.0.1:5056 -L 5070:127.0.0.1:5070 -L 5080:127.0.0.1:5080 -L 5090:127.0.0.1:5090 FG-W11-ICON-DEV
|
||
```
|
||
|
||
## 几个容易踩的点
|
||
|
||
- **库是 iXserverLoop,不是 iXsererTest。** FeatureTest 每个方法都 drop 重建 iXsererTest,
|
||
反过来闭环 API 的连接池连着它会让 FeatureTest 无限卡在删库上。
|
||
- **API 从 `run\ixserver` 跑,不从 `API\` 源码目录跑。** 编译 FeatureTest 会刷新 `API\bin` 里的模块 dll,
|
||
正在跑的站点会被回收、甚至换成依赖不全的版本。
|
||
- **`reset` 把建库与 `loop_patch.sql` 绑在一起。** 种子里有真格式的 FB token 与 api.commas.hk 等真实 webhook,
|
||
补丁把它们全换成假值 / 黑洞,并在末尾自检;不提供「只建不补」。
|
||
- **`OAuth_Authority` 必须逐字等于本地 ABP 签出 token 的 `iss`。** IdentityServer4 没设 IssuerUri,
|
||
iss 取请求的 Host,所以全链路统一用 `https://localhost:44332`,换成 127.0.0.1 就全部 401。
|
||
- **签名密钥不在库里**,在 ABP 进程工作目录的 `tempkey.jwk`。deploy 删掉仓库里那把开发密钥,
|
||
首次 `up` 时 ABP 自己生成一把,留存到 `run\abp-key\`,之后重新部署沿用同一把。
|
||
- **备份在 SQL 实例的默认备份目录**(`*.loop.bak`),不在 `run\backup\`:SQL 服务账号对 `C:\Projects` 不一定有写权限。
|
||
- **进程用 WMI(Win32_Process.Create)起**,不用 Start-Process:经 SSH 起的进程会随会话一起被杀。
|
||
pid 记在 `run\pids\`,`down` 按进程树杀。
|
||
- **VS Code 的自动端口转发会抢闭环端口。** 在 winbox 上用 VS Code Remote-SSH 连 Mac 时,它从终端输出里认
|
||
`localhost:端口`,然后在 winbox 本机占住同一个端口转发回 Mac,闭环角色就报「端口被 Code 占着」。
|
||
Mac 的 `~/.vscode-server/data/Machine/settings.json` 已设 `remote.autoForwardPorts=false`、
|
||
`remote.restoreForwardedPorts=false`;已经转发出去的要在 VS Code「端口」面板里停掉。
|
||
- **WMI 起的进程只有系统环境变量。** `TEMP` 是 `C:\Windows\TEMP`,ASP.NET 编译临时目录也会退回系统目录,
|
||
没写权限,首个请求就 500。`loop.ps1` 给每个角色设了 `TEMP`/`TMP` 指到 `run\data\temp`,
|
||
并在 Web.config 的 `<compilation>` 上写 `tempDirectory`。
|
||
- **ABP 的 HTTPS 证书用的是 IIS Express 自带的 localhost 证书**(LocalMachine\My,到 2030 年,已在当前用户受信任根里)。
|
||
winbox 的 ASP.NET dev 证书 2026-05 已过期;用 IIS Express 这张,iXserver(.NET Framework)连 ABP 不用另外信任、也不弹框。
|
||
- **ABP 的各个 DbContext 按名字找连接串,找不到退回 `Default`**,而仓库 `appsettings.json` 的 `Default` 指向公司内网的库。
|
||
`appsettings.Loop.json` 把所有连接串都盖成本机 iCONAbpFX。
|
||
- PowerShell 5.1 的两个坑已经在 `loop.ps1` 里绕开:原生命令往 stderr 写一行就抛异常(统一走 `Invoke-Native`);
|
||
`Get-Content` 默认按 GBK 读无 BOM 的 UTF-8(拷配置用 `Copy-Item`,脚本文件一律带 BOM)。
|
||
- **iXserver 的主日志在 `run\ixserver\Log\{Debug,Information,Warning,Error}\<日期>\`**(注入的 ILogger,内部步骤很全,观察台就读它)。
|
||
`run\data\API_Log` 是静态 `Logger` 写的另一份,几乎是空的,别看它下结论。排查先看 `Log\Error`。
|
||
`deploy` 的 robocopy 排除了 `Log` / `Logs`,重新部署不会清掉日志。
|
||
- `deployed.json` 记录每次部署时两个源码仓库的 commit 与未提交文件。闭环结果离开「当时部署的是哪个版本」没法解读,
|
||
跑场景的记录里引用它。注意 winbox 上 iXserver 仓库的 HEAD 不随 `sync.sh` 前进(只推文件),
|
||
`commit` 字段可能停在很久以前,以 `uncommitted` 清单和 Mac 上的提交为准。
|
||
|
||
## 闭环专用凭据(假值,可公开)
|
||
|
||
见 `config\loop.psd1` 的 `Secrets`:setsail 与 FX_App 的 client secret、ABP admin 密码、所有渠道 token 的替身。
|
||
staging 的 secret 明文不出现在这个仓库里。
|