Files
olons_server/docs/superpowers/specs/2026-10-19-customer-service-im-reliability-design.md
T

2.9 KiB

客服 IM 投递可靠性设计

目标

修复 OLONS 会员端在 WebSocket 异常断线后无法继续接收客服文本或图片的问题,并保证 IM API、文件和 WebSocket 全部通过用户当前访问的前端域名转发。

范围

  • olons_server 会员客服客户端的断线恢复、连接状态和媒体加载错误处理。
  • olons_server 客服会话返回给浏览器的公开端点。
  • im_webapp 生产构建中的固定公网域名。
  • 单机 Compose Caddy 的同源路径路由和部署契约。
  • 生产发布及五个前端域名的文本、图片、WebSocket 验收。

不修改会员、消息或文件业务数据,不改支付、提现及其他业务功能。

架构

浏览器公开端点使用相对路径:/v1/im、/v0/file、/v0/channels。客户端以 window.location.origin 解析 HTTP/文件地址,并将当前页面协议转换为 ws 或 wss。因此同一镜像在 olons.yuexuan.shop 和三个公测域名下会自动使用当前域名,不读取或信任任意 Host Header。

Caddy 在五个前端域名中优先把上述路径代理到 im-server:6060,其余路径仍进入原来的前端或 OLONS 服务。代理响应明确禁止缓存。olons-server 自身调用 IM 时使用 Docker 网络中的 im-server:6060,不再绕行 Cloudflare。

断线恢复

CustomerServiceChat 保存 token、当前 Topic 和最新 seq。首次连接仍执行 connect、token 登录和历史订阅。SDK 重新建立 WebSocket 后,客户端再次 token 登录,重新订阅当前 Topic,并通过 later-data 查询补拉本地最后 seq 之后的数据。恢复过程串行化,避免多个 reconnect 回调造成重复登录或订阅。

页面接收连接状态:connecting、online、reconnecting、offline。断线时保留已显示消息但禁止发送,恢复成功后解除禁止。主动离开页面不触发恢复。

图片处理

上传使用 X-MeetingIM-APIKey 和 Authorization: Token <token> Header,不再把 token 放在 URL 查询参数中。下载继续使用当前域名;图片或视频加载失败时显示失败提示和重试入口,不能静默显示空白。

测试

  • TypeScript 单测覆盖相对端点解析、首次订阅、断线重连、重新登录、重新订阅、补拉和主动断开。
  • Go 单测覆盖客服会话始终返回相对公开端点。
  • im_webapp 工作流契约禁止固定 im-api.yuexuan.shop 和旧 118im.com 文件/WS地址。
  • 部署契约要求五个域名都有三条同源路由,并保证 catch-all 顺序正确。
  • 生产验收验证 JSON API、文件、WebSocket 101、断线恢复后的文本和图片,不以数据库序号代替浏览器展示验收。

回滚

应用镜像可回滚到发布前 digest;Caddy 修改前保留生产文件副本。回滚只涉及 olons-server、im-webapp 和 Caddy,不修改数据库或 MinIO 数据。