Skip to content

IM · WuKongIM 长连接与会话列表策略 ​

创建: 2026-07-25 · 2026-07-31 归入学习笔记(原理说明,非开发待办)
状态:现阶段共识(策略 A)· 摘要已并入 13-IM「连接与会话列表约定」
关联:ADR-025 · 欠账 迭代主线 §2.0
App:my-tandem-travel · pages/chat/chat.vue · utils/im/session.js · utils/im/conversation-cache.js


TL;DR ​

  1. WuKongIM 是 WebSocket 长连接 + 心跳,不是「发完就断」的短请求。
  2. 本项目现状 = 策略 A:进消息 Tab 才连,连上后保持。实时性要求不高,现阶段够用;1000 在线量级对 WuKongIM 通常不是瓶颈。
  3. 「重进消息 Tab 后最后一条/未读被清空」不是重连本身清了消息,而是 GET /conversations/list 在 webhook 未回写时返回 lastMessagePreview=null / unreadCount=0,前端整表覆盖把内存里的实时摘要冲掉了。详情页历史走 WuKong messagesync,所以点进去内容还在。
  4. 前端已用 本地摘要缓存 + 合并策略 兜底;业务库摘要仍依赖 webhook(U1),运维侧确认重启后才是权威源。

1. 连接模型是什么 ​

App ──WebSocket(长连接)──► WuKongIM(收发 / 心跳 / 离线存储)
App ──REST /api/im/*────► Spring(Token / 好友 / 会话元数据 / 已读清零)
WuKongIM ──webhook──────► Spring(回写 last_message_* / unread_count,不存正文)
概念说明
长连接连上后心跳维持(wk.yaml heartbeat_interval: 30),直到断网 / 杀进程 / disconnect / 被踢
在线推送已连接时 SDK chatManager.addMessageListener 收包 → uni.$emit('im:message')
离线历史未连接期间消息存在 WuKong;再连后靠 channel/messagesync 拉
会话列表摘要理想情况来自业务库(webhook);正文永不进 Spring

配置参考(理论值,实战受内存限制):

  • websocket.max_conn: 100000
  • compose 里 WuKongIM 内存约 300M → 真瓶颈往往是内存 / FD,不是「注册用户数」

2. 本项目当前行为(对照联调现象) ​

阶段行为体验
从未点过「消息」不 ensureConnected收不到实时推送
进入消息 TabonShow → ensureConnected + 拉 REST 列表开始实时
连上后切到「我的」等 Tab连接保持仍可 toast / 红点(已验证)
杀进程后再进需再次进消息 Tab 才连符合策略 A

产品取舍:不要求「人在任意 Tab 都秒推」;要求「点开消息 Tab 能看到最新摘要 + 进详情能看历史」。


3. 三种策略对比 ​

策略做法体验连接压力复杂度本阶段
A. 懒连接 + 连上保持进消息才连,不主动 idle 断中中(活跃用户)低✅ 采用
B. 启动常驻App 启动 / 登录后就连最好最高低用户过万或客诉多再议
C. 懒连接 + 空闲断开离开消息相关页 N 分钟 disconnect,再进 sync略差最低中连接告警后再议

业界常见:前台长连 + 后台系统推送(微信订阅消息 / APNs 等)。我们未接系统推送前,A 是合理默认。


4. 「重进 Tab 摘要被清空」根因与修复 ​

根因链 ​

  1. 实时消息更新的是 前端内存(及后来加的本地缓存)
  2. onShow / 重连成功后调用 loadConversations(true) → GET /api/im/conversations/list
  3. 若 WuKong webhook 未生效,库里 last_message_preview / unread_count 仍是 null / 0
  4. 旧逻辑:整表替换 conversations = apiList → UI 预览与未读被冲空
  5. 详情页走 WuKong sync → 聊天内容仍在(与列表摘要无关)

这与「重新连接 IM」相关,但是 重连触发了 REST 刷新,不是 WS 把历史删了。

修复(App) ​

  • utils/im/conversation-cache.js:按用户缓存会话摘要
  • loadConversations(true):mergeConversationLists(api, local)
    • API 有预览 → 以 API 为主(webhook 正常时)
    • API 无预览 → 保留本地/缓存 预览与未读
  • 实时更新 / 标已读时同步写缓存

仍建议运维确认(权威源) ​

bash
# 服务器确认 wk.yaml webhook.enabled=true 且指向 tour-mate-app
# 改过配置后需:./deploy.sh restart wukongim
# 发一条消息后查 im_conversations.last_message_preview 是否非空

前端兜底保证「webhook 挂了也能用」;webhook 通了之后列表以服务端为准更一致(多端)。


5. 容量粗估(回答「1000 用户压力」) ​

  • 在线连接数 ≈ 同时开着 App 且已进过消息 Tab 的用户,不是注册用户总数。
  • 例:DAU 1000、同时在线 10%、其中一半进过消息 → 约 50 条长连接,可忽略。
  • 单机 WuKongIM 配置 max_conn 很大;小机器先看 RSS / 打开文件数。
  • 优化顺序:监控 → 再考虑策略 C;不要过早为省连接牺牲体验。

6. 何时升级策略 ​

触发动作
客诉「不在消息页完全收不到、红点也不准」且 webhook 已通考虑策略 B,或未读 REST 轮询
在线连接 / 内存告警策略 C(idle disconnect)
需要杀进程后仍触达接微信订阅消息 / 厂商推送(另开专题)

7. 相关代码路标 ​

端路径
懒连接App utils/im/session.js · pages/chat/chat.vue onShow
收消息App utils/im/wukong-client.js → chatManager.addMessageListener
列表合并App utils/im/conversation-cache.js
会话 RESTSpring ImConversationController
已读清零PUT /api/im/conversations/{id}/read(U2)
WebhookPOST /api/im/webhook/wukong · wk.yaml webhook 段

8. 共识(可勾选) ​

  • [x] 现阶段锁定 策略 A,不改为启动常驻
  • [x] 列表摘要:本地缓存兜底 + webhook 权威(运维确认);未读仅「点进会话」清零(readAt)
  • [x] 图片 / 语音发送:上传 scene=chat → MessageImage(2) / 自定义 Voice(3);位置仍未开放
  • [ ] 连接数监控 / idle 断开:过后再开
  • [ ] 系统级推送:另开专题
  • [ ] 位置消息 / 多图 / 视频:延后
  • [ ] 聊天内容安全真实挂钩:延后(M2)

Powered by VitePress