feat(chat): 新增聊天业务模块

范围:src/business/chat/
- 实现 ChatService 聊天业务服务(登录/登出/消息发送/位置更新)
- 实现 ChatSessionService 会话管理服务(会话创建/销毁/上下文注入)
- 实现 ChatFilterService 消息过滤服务(频率限制/敏感词/权限验证)
- 实现 ChatCleanupService 会话清理服务(定时清理过期会话)
- 添加完整的单元测试覆盖
- 添加模块 README 文档
This commit is contained in:
moyin
2026-01-14 19:17:32 +08:00
parent 5bcf3cb678
commit 30a4a2813d
11 changed files with 3298 additions and 0 deletions

128
src/business/chat/README.md Normal file
View File

@@ -0,0 +1,128 @@
# Chat 聊天业务模块
Chat 模块是游戏服务器的核心聊天业务层,负责实现游戏内实时聊天功能,包括玩家会话管理、消息过滤、位置追踪和 Zulip 异步同步。该模块通过 SESSION_QUERY_SERVICE 接口向其他业务模块提供会话查询能力。
## 对外提供的接口
### ChatService
#### handlePlayerLogin(request: PlayerLoginRequest): Promise<LoginResponse>
处理玩家登录,验证 Token 并创建游戏会话。
#### handlePlayerLogout(socketId: string, reason?: string): Promise<void>
处理玩家登出,清理会话和相关资源。
#### sendChatMessage(request: ChatMessageRequest): Promise<ChatMessageResponse>
发送聊天消息,包含内容过滤、实时广播和 Zulip 异步同步。
#### updatePlayerPosition(request: PositionUpdateRequest): Promise<boolean>
更新玩家在游戏地图中的位置。
#### getChatHistory(query: object): Promise<object>
获取聊天历史记录。
#### getSession(socketId: string): Promise<GameSession | null>
获取指定 WebSocket 连接的会话信息。
### ChatSessionService (实现 ISessionManagerService)
#### createSession(socketId, userId, zulipQueueId, username?, initialMap?, initialPosition?): Promise<GameSession>
创建新的游戏会话,建立 WebSocket 与用户的映射关系。
#### getSession(socketId: string): Promise<GameSession | null>
获取会话信息并更新最后活动时间。
#### destroySession(socketId: string): Promise<boolean>
销毁会话并清理相关资源。
#### injectContext(socketId: string, mapId?: string): Promise<ContextInfo>
根据玩家位置注入聊天上下文Stream/Topic
#### updatePlayerPosition(socketId, mapId, x, y): Promise<boolean>
更新玩家位置,支持跨地图切换。
#### getSocketsInMap(mapId: string): Promise<string[]>
获取指定地图中的所有在线玩家 Socket。
#### cleanupExpiredSessions(timeoutMinutes?: number): Promise<object>
清理过期会话,返回清理数量和 Zulip 队列 ID 列表。
### ChatFilterService
#### validateMessage(userId, content, targetStream, currentMap): Promise<object>
综合验证消息,包含频率限制、内容过滤和权限验证。
#### filterContent(content: string): Promise<ContentFilterResult>
过滤消息内容,检测敏感词、重复字符和恶意链接。
#### checkRateLimit(userId: string): Promise<boolean>
检查用户发送消息的频率是否超限。
#### validatePermission(userId, targetStream, currentMap): Promise<boolean>
验证用户是否有权限向目标频道发送消息。
### ChatCleanupService
#### triggerCleanup(): Promise<{ cleanedCount: number }>
手动触发会话清理,返回清理的会话数量。
## 使用的项目内部依赖
### IZulipClientPoolService (来自 core/zulip_core)
Zulip 客户端连接池服务,用于创建/销毁用户客户端和发送消息。
### IApiKeySecurityService (来自 core/zulip_core)
API Key 安全服务,用于获取和删除用户的 Zulip API Key。
### IZulipConfigService (来自 core/zulip_core)
Zulip 配置服务,提供地图与 Stream 的映射关系和附近对象查询。
### IRedisService (来自 core/redis)
Redis 缓存服务,用于存储会话数据、地图玩家列表和频率限制计数。
### LoginCoreService (来自 core/login_core)
登录核心服务,用于验证 JWT Token。
### ISessionManagerService (来自 core/session_core)
会话管理接口定义ChatSessionService 实现此接口供其他模块依赖。
## 核心特性
### 实时聊天 + 异步同步架构
- 🚀 游戏内实时广播:消息直接广播给同地图玩家,延迟极低
- 🔄 Zulip 异步同步:消息异步存储到 Zulip保证持久化
- ⚡ 低延迟体验:先广播后同步,不阻塞用户操作
### 基于位置的聊天上下文
- 根据玩家当前地图自动确定 Zulip Stream
- 根据玩家位置附近的对象自动确定 Topic
- 支持跨地图切换时自动更新聊天频道
### 会话生命周期管理
- 自动清理旧会话,防止重复登录
- 定时清理过期会话(默认 30 分钟无活动)
- 支持手动触发清理操作
### 内容安全和频率控制
- 敏感词过滤(支持替换和阻止两种模式)
- 频率限制(默认 60 秒内最多 10 条消息)
- 恶意链接检测和黑名单域名过滤
- 重复字符和刷屏检测
## 潜在风险
### Redis 连接故障风险
- 会话数据存储在 Redis连接故障会导致会话丢失
- 缓解措施Redis 集群部署、连接重试机制
### Zulip 同步延迟风险
- 异步同步可能导致消息在 Zulip 中延迟出现
- 缓解措施:消息队列、重试机制、失败告警
### 高并发广播性能风险
- 同一地图玩家过多时广播性能下降
- 缓解措施:分片广播、消息合并、限制单地图人数
### 会话清理遗漏风险
- 定时清理可能遗漏部分过期会话
- 缓解措施多次清理、Redis 过期策略配合