zhibo/直播IM系统技术方案.md

29 KiB
Raw Permalink Blame History

直播IM系统技术方案

一、项目概述

1.1 项目目标

搭建一个面向直播场景的即时通讯系统支持1-10万用户规模一周内完成MVP版本交付。

1.2 核心场景

直播场景

  • 直播间实时弹幕
  • 主播与观众互动消息
  • 直播间礼物打赏
  • 进入/离开直播间通知

社交交友场景

  • 用户一对一私聊
  • 好友申请与通知
  • 私聊礼物赠送
  • 语音消息发送
  • 图片/视频分享
  • 表情包发送
  • 消息已读/未读状态

互动场景

  • 作品评论通知
  • 点赞通知
  • 关注/粉丝通知
  • @提醒通知
  • 系统公告推送

1.3 技术选型原则

  • 快速开发,优先使用成熟方案
  • 架构简单,便于维护和扩展
  • 成本可控,适合初期规模

二、系统架构设计

2.1 整体架构

客户端层Android App
    ↓
API网关层Nginx
    ↓
业务服务层
    ├── IM服务WebSocket/长连接)
    ├── REST API服务HTTP
    └── 消息推送服务
    ↓
数据存储层
    ├── MySQL用户数据、消息记录
    ├── Redis在线状态、消息缓存
    └── MongoDB可选消息归档

2.2 核心模块

2.2.1 连接管理模块

  • WebSocket长连接维护
  • 心跳检测30秒间隔
  • 断线重连机制
  • 在线状态管理

2.2.2 消息路由模块

  • 单聊消息路由
  • 群聊(直播间)消息广播
  • 消息优先级队列
  • 消息去重

2.2.3 消息存储模块

  • 离线消息存储
  • 历史消息查询
  • 消息已读状态
  • 消息漫游7天

2.2.4 业务功能模块

  • 弹幕发送与接收
  • 礼物打赏消息(直播间+私聊)
  • 好友关系管理
  • 消息已读回执
  • 语音消息处理
  • 图片/视频消息
  • 系统通知
  • 敏感词过滤
  • 消息撤回

三、技术实现方案

3.1 通信协议选择

方案一WebSocket推荐

优点:

  • 双向实时通信
  • 浏览器原生支持
  • 开发简单,调试方便
  • 适合直播弹幕场景

实现:

协议ws:// 或 wss://生产环境必须用wss
框架Spring Boot + Spring WebSocket
心跳客户端30秒发送ping服务端响应pong

方案二MQTT备选

优点:

  • 轻量级协议
  • 支持QoS消息质量保证
  • 适合物联网和移动场景

缺点:

  • 需要额外的Broker如Mosquitto、EMQ
  • 学习成本稍高

建议: 一周交付选WebSocket后期可扩展MQTT

3.2 消息格式设计

3.2.1 通用消息结构JSON

{
  "msgId": "uuid",
  "msgType": "text|image|gift|system|barrage",
  "fromUserId": "发送者ID",
  "toUserId": "接收者ID私聊",
  "roomId": "直播间ID弹幕",
  "content": "消息内容",
  "timestamp": 1640000000000,
  "extra": {
    "nickname": "用户昵称",
    "avatar": "头像URL",
    "giftId": "礼物ID打赏消息",
    "giftCount": 1
  }
}

3.2.2 消息类型定义

类型 说明 场景
text 文本消息 私聊、弹幕
image 图片消息 私聊
video 视频消息 私聊
voice 语音消息 私聊
emoji 表情包消息 私聊
gift 礼物打赏 直播间、私聊
barrage 弹幕 直播间
system 系统通知 全局
friend_request 好友申请 社交
friend_accept 好友通过 社交
like 点赞通知 社交
comment 评论通知 社交
follow 关注通知 社交
at_mention @提醒 社交
enter_room 进入直播间 直播间
leave_room 离开直播间 直播间
recall 消息撤回 私聊

3.3 数据库设计

3.3.1 MySQL表结构

用户表user

CREATE TABLE `user` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `username` VARCHAR(50) UNIQUE NOT NULL,
  `nickname` VARCHAR(50),
  `avatar` VARCHAR(255),
  `status` TINYINT DEFAULT 1 COMMENT '1-正常 0-禁用',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

会话表conversation

CREATE TABLE `conversation` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `user_id` BIGINT NOT NULL,
  `target_id` BIGINT NOT NULL COMMENT '对方用户ID或直播间ID',
  `type` TINYINT NOT NULL COMMENT '1-单聊 2-直播间',
  `last_msg_id` BIGINT,
  `last_msg_time` DATETIME,
  `unread_count` INT DEFAULT 0,
  `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_user_id (user_id),
  UNIQUE KEY uk_user_target (user_id, target_id, type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

消息表message

CREATE TABLE `message` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `msg_id` VARCHAR(64) UNIQUE NOT NULL,
  `msg_type` VARCHAR(20) NOT NULL,
  `from_user_id` BIGINT NOT NULL,
  `to_user_id` BIGINT COMMENT '私聊接收者',
  `room_id` BIGINT COMMENT '直播间ID',
  `content` TEXT,
  `extra` JSON COMMENT '扩展字段图片URL、语音时长、礼物信息等',
  `status` TINYINT DEFAULT 1 COMMENT '1-正常 2-撤回 3-删除',
  `is_read` TINYINT DEFAULT 0 COMMENT '0-未读 1-已读',
  `read_at` DATETIME COMMENT '已读时间',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_from_user (from_user_id, created_at),
  INDEX idx_to_user (to_user_id, created_at),
  INDEX idx_room (room_id, created_at),
  INDEX idx_msg_id (msg_id),
  INDEX idx_unread (to_user_id, is_read)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

好友关系表friend

CREATE TABLE `friend` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `user_id` BIGINT NOT NULL,
  `friend_id` BIGINT NOT NULL,
  `remark` VARCHAR(50) COMMENT '好友备注',
  `status` TINYINT DEFAULT 1 COMMENT '1-正常 2-拉黑',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_user_friend (user_id, friend_id),
  INDEX idx_user_id (user_id),
  INDEX idx_friend_id (friend_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

好友申请表friend_request

CREATE TABLE `friend_request` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `from_user_id` BIGINT NOT NULL,
  `to_user_id` BIGINT NOT NULL,
  `message` VARCHAR(200) COMMENT '申请留言',
  `status` TINYINT DEFAULT 0 COMMENT '0-待处理 1-已同意 2-已拒绝',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_to_user (to_user_id, status),
  INDEX idx_from_user (from_user_id),
  UNIQUE KEY uk_from_to (from_user_id, to_user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

礼物记录表gift_record

CREATE TABLE `gift_record` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `from_user_id` BIGINT NOT NULL COMMENT '送礼者',
  `to_user_id` BIGINT NOT NULL COMMENT '收礼者',
  `gift_id` INT NOT NULL,
  `gift_name` VARCHAR(50),
  `gift_price` INT NOT NULL COMMENT '礼物价格(金币)',
  `count` INT DEFAULT 1 COMMENT '数量',
  `total_price` INT NOT NULL COMMENT '总价',
  `room_id` BIGINT COMMENT '直播间ID直播间送礼',
  `scene` VARCHAR(20) NOT NULL COMMENT 'live-直播间 chat-私聊',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_from_user (from_user_id, created_at),
  INDEX idx_to_user (to_user_id, created_at),
  INDEX idx_room (room_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

直播间表live_room

CREATE TABLE `live_room` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `room_id` VARCHAR(50) UNIQUE NOT NULL,
  `anchor_id` BIGINT NOT NULL COMMENT '主播ID',
  `title` VARCHAR(100),
  `cover` VARCHAR(255),
  `status` TINYINT DEFAULT 1 COMMENT '1-直播中 0-已结束',
  `online_count` INT DEFAULT 0,
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_anchor (anchor_id),
  INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.3.2 Redis数据结构

在线用户Hash

Key: online:users
Field: userId
Value: {serverId, connectTime, lastHeartbeat}

直播间在线列表Set

Key: room:online:{roomId}
Member: userId

用户连接映射String

Key: user:connection:{userId}
Value: {serverId, sessionId}

离线消息队列List

Key: offline:msg:{userId}
Value: [msgId1, msgId2, ...]

消息缓存StringTTL=7天

Key: msg:cache:{msgId}
Value: JSON消息体

四、核心功能实现

4.1 连接建立流程

1. 客户端发起WebSocket连接
   ws://domain/ws?token=xxx

2. 服务端验证token
   - 解析JWT token
   - 验证用户身份
   - 检查用户状态

3. 连接成功
   - 保存连接到内存Map
   - 更新Redis在线状态
   - 返回连接成功消息

4. 拉取离线消息
   - 从Redis获取离线消息ID列表
   - 批量查询消息详情
   - 推送给客户端

5. 启动心跳
   - 客户端每30秒发送ping
   - 服务端响应pong
   - 超过90秒无心跳则断开连接

4.2 单聊消息流程

1. 客户端发送消息
   {
     "action": "sendMessage",
     "toUserId": "123",
     "msgType": "text",
     "content": "你好"
   }

2. 服务端处理
   - 生成msgIdUUID
   - 敏感词过滤
   - 保存到MySQL
   - 缓存到Redis7天

3. 消息路由
   - 查询接收者在线状态
   - 如果在线通过WebSocket推送
   - 如果离线:存入离线消息队列

4. 客户端接收
   - 收到消息后发送ACK确认
   - 更新会话列表
   - 显示消息内容

5. 已读回执(可选)
   - 用户查看消息后发送已读状态
   - 更新消息已读标记
   - 通知发送方

4.3 直播间弹幕流程

1. 用户进入直播间
   - 发送enterRoom消息
   - 加入Redis直播间在线集合
   - 广播进入消息(可选)

2. 发送弹幕
   {
     "action": "sendBarrage",
     "roomId": "room_001",
     "content": "主播666"
   }

3. 服务端处理
   - 频率限制1秒1条
   - 敏感词过滤
   - 保存到MySQL可异步
   - 不缓存到Redis弹幕量大

4. 消息广播
   - 获取直播间所有在线用户
   - 遍历推送消息
   - 失败的用户从在线列表移除

5. 离开直播间
   - 发送leaveRoom消息
   - 从Redis在线集合移除

4.4 礼物打赏流程

场景一:直播间送礼

1. 客户端发送礼物
   {
     "action": "sendGift",
     "roomId": "room_001",
     "anchorId": "456",
     "giftId": "gift_001",
     "count": 1
   }

2. 服务端处理
   - 验证用户余额
   - 扣除金币
   - 增加主播收益
   - 保存打赏记录

3. 消息广播
   - 构造礼物消息
   - 广播到直播间所有用户
   - 触发礼物动画

4. 通知主播
   - 发送私信通知
   - 更新收益统计

场景二:私聊送礼(社交场景)

1. 客户端发送礼物
   {
     "action": "sendPrivateGift",
     "toUserId": "789",
     "giftId": "gift_002",
     "count": 1,
     "message": "送你一朵玫瑰"
   }

2. 服务端处理
   - 验证用户余额
   - 扣除金币
   - 增加对方收益
   - 保存礼物记录
   - 构造礼物消息

3. 消息推送
   - 推送给接收者
   - 显示礼物卡片
   - 触发礼物动画
   - 更新会话列表

4. 收益通知
   - 发送收益通知
   - 更新用户余额

4.5 好友关系管理

添加好友流程

1. 发送好友申请
   {
     "action": "sendFriendRequest",
     "toUserId": "123",
     "message": "你好,可以加个好友吗?"
   }

2. 服务端处理
   - 检查是否已是好友
   - 检查是否已发送过申请
   - 保存好友申请记录
   - 构造申请通知消息

3. 推送通知
   - 推送给目标用户
   - 显示好友申请红点
   - 更新申请列表

4. 处理申请
   {
     "action": "handleFriendRequest",
     "requestId": "456",
     "accept": true
   }

5. 同意后处理
   - 更新申请状态
   - 双向添加好友关系
   - 发送同意通知
   - 创建会话

删除好友流程

1. 客户端请求删除
   {
     "action": "deleteFriend",
     "friendId": "123"
   }

2. 服务端处理
   - 删除好友关系
   - 保留历史消息(可选)
   - 发送删除通知(可选)

4.6 多媒体消息处理

图片消息流程

1. 上传图片
   POST /api/upload/image
   - 客户端先上传图片到服务器
   - 返回图片URL和缩略图URL

2. 发送图片消息
   {
     "action": "sendMessage",
     "toUserId": "123",
     "msgType": "image",
     "content": "imageUrl",
     "extra": {
       "thumbnail": "thumbnailUrl",
       "width": 1080,
       "height": 1920,
       "size": 102400
     }
   }

3. 服务端处理
   - 验证图片URL合法性
   - 保存消息记录
   - 推送给接收者

4. 客户端显示
   - 先显示缩略图
   - 点击查看大图
   - 支持图片保存

语音消息流程

1. 录制语音
   - 客户端录制语音最长60秒
   - 转换为MP3/AAC格式
   - 上传到服务器

2. 发送语音消息
   {
     "action": "sendMessage",
     "toUserId": "123",
     "msgType": "voice",
     "content": "voiceUrl",
     "extra": {
       "duration": 15,
       "size": 51200
     }
   }

3. 服务端处理
   - 验证语音文件
   - 保存消息记录
   - 推送给接收者

4. 客户端播放
   - 显示语音时长
   - 点击播放
   - 显示播放进度
   - 标记已读

视频消息流程

1. 上传视频
   POST /api/upload/video
   - 限制视频大小如50MB
   - 限制视频时长如30秒
   - 生成视频封面

2. 发送视频消息
   {
     "action": "sendMessage",
     "toUserId": "123",
     "msgType": "video",
     "content": "videoUrl",
     "extra": {
       "cover": "coverUrl",
       "duration": 20,
       "width": 720,
       "height": 1280,
       "size": 5242880
     }
   }

3. 客户端显示
   - 显示视频封面
   - 显示时长标识
   - 点击播放

4.7 消息已读回执

已读状态更新

1. 用户查看消息
   {
     "action": "markAsRead",
     "conversationId": "123",
     "lastMsgId": "msg_456"
   }

2. 服务端处理
   - 更新消息已读状态
   - 更新会话未读数
   - 记录已读时间

3. 推送已读回执
   - 通知发送方消息已读
   - 显示"已读"标识
   - 更新发送方会话列表

未读消息统计

1. 获取未读数
   GET /api/message/unreadCount
   Response: {
     "totalUnread": 15,
     "conversations": [
       {"conversationId": 1, "unread": 5},
       {"conversationId": 2, "unread": 10}
     ]
   }

2. 实时更新
   - 收到新消息时更新未读数
   - 标记已读时减少未读数
   - 推送未读数变化

4.8 消息撤回功能

撤回流程

1. 客户端请求撤回
   {
     "action": "recallMessage",
     "msgId": "msg_123"
   }

2. 服务端验证
   - 检查消息是否存在
   - 检查是否是发送者本人
   - 检查是否在2分钟内
   - 更新消息状态为已撤回

3. 推送撤回通知
   - 通知接收者消息已撤回
   - 显示"对方撤回了一条消息"
   - 更新会话最后一条消息

4. 客户端处理
   - 移除或替换消息内容
   - 显示撤回提示

4.9 社交互动通知

点赞通知

1. 用户点赞作品/评论
   POST /api/like
   {
     "targetType": "work|comment",
     "targetId": 123
   }

2. 服务端处理
   - 保存点赞记录
   - 构造通知消息
   - 推送给作品作者

3. 通知消息格式
   {
     "type": "like",
     "data": {
       "userId": 456,
       "username": "张三",
       "avatar": "xxx",
       "targetType": "work",
       "targetId": 123,
       "targetTitle": "作品标题",
       "timestamp": 1640000000000
     }
   }

评论通知

1. 用户发表评论
   POST /api/comment
   {
     "workId": 123,
     "content": "很棒的作品!"
   }

2. 服务端处理
   - 保存评论记录
   - 构造通知消息
   - 推送给作品作者

3. @提醒处理
   - 解析评论中的@用户
   - 发送@提醒通知
   - 推送给被@的用户

关注通知

1. 用户关注他人
   POST /api/follow
   {
     "targetUserId": 123
   }

2. 服务端处理
   - 保存关注关系
   - 构造通知消息
   - 推送给被关注者

3. 通知消息
   {
     "type": "follow",
     "data": {
       "userId": 456,
       "username": "张三",
       "avatar": "xxx",
       "timestamp": 1640000000000
     }
   }

4.5 系统通知流程

1. 后台触发通知
   - 关注通知
   - 点赞通知
   - 评论通知
   - 系统公告
   - 审核通知

2. 服务端处理
   - 构造系统消息
   - 保存到MySQL
   - 推送给目标用户

3. 客户端接收
   - 显示通知红点
   - 弹出提示(可选)
   - 更新通知列表

五、性能优化方案

5.1 连接优化

单机连接数优化

  • 使用Netty或Spring WebFlux异步非阻塞
  • 单机支持10万+连接
  • 调整系统参数ulimit -n 100000

连接保活

  • 客户端心跳30秒
  • 服务端超时90秒
  • 减少无效连接占用

5.2 消息优化

弹幕限流

  • 用户级别1秒1条
  • 直播间级别每秒1000条超过则丢弃
  • 使用Redis令牌桶算法

消息批量处理

  • 弹幕批量入库100条/批次)
  • 离线消息批量拉取50条/次)
  • 减少数据库IO

消息压缩

  • 启用WebSocket压缩permessage-deflate
  • 减少30-50%流量

5.3 存储优化

MySQL优化

  • 消息表按月分表
  • 历史消息归档到MongoDB
  • 只保留3个月热数据

Redis优化

  • 消息缓存设置TTL7天
  • 使用Redis Cluster后期扩展
  • 离线消息队列限制长度最多100条

5.4 广播优化

直播间消息广播

  • 异步推送,不阻塞主线程
  • 失败重试1次超时则放弃
  • 单次广播超时时间100ms

分组广播(后期优化)

  • 将直播间用户分组每组1000人
  • 多线程并行推送
  • 提升广播效率

六、技术栈选型

6.1 后端技术栈

核心框架

  • Spring Boot 2.7+
  • Spring WebSocket
  • Spring Data JPA / MyBatis-Plus

中间件

  • MySQL 8.0(主数据库)
  • Redis 6.0+(缓存、在线状态)
  • Nginx反向代理、负载均衡

工具库

  • JWT用户认证
  • JacksonJSON序列化
  • Hutool工具类
  • Lombok简化代码

6.2 前端技术栈Android

网络库

  • OkHttpHTTP请求
  • OkHttp WebSocket长连接

UI框架

  • Material Design Components
  • RecyclerView消息列表
  • ViewPager2直播间

工具库

  • GsonJSON解析
  • Glide图片加载
  • EventBus事件总线

6.3 开发工具

  • IntelliJ IDEA后端开发
  • Android StudioAndroid开发
  • PostmanAPI测试
  • Redis Desktop ManagerRedis管理
  • Navicat数据库管理

七、部署方案

7.1 服务器配置(初期)

单机部署方案

服务器阿里云ECS
配置4核8G 5M带宽
系统CentOS 7.9

服务部署:
- Nginx80/443端口
- Spring Boot IM服务8080端口
- MySQL3306端口
- Redis6379端口

预估支持规模

  • 同时在线5000人
  • 单直播间500人
  • 消息吞吐5000条/秒

7.2 扩展方案(后期)

水平扩展

负载均衡Nginx
    ↓
IM服务集群3台
    ↓
Redis集群主从
    ↓
MySQL主从读写分离

支持规模

  • 同时在线5万人
  • 单直播间5000人
  • 消息吞吐5万条/秒

八、开发计划7天

Day 1-2基础架构搭建

  • 搭建Spring Boot项目
  • 集成WebSocket
  • 配置MySQL、Redis
  • 实现用户认证JWT
  • 实现连接管理模块

Day 3-4核心功能开发

  • 实现单聊消息收发
  • 实现直播间弹幕
  • 实现离线消息
  • 实现消息存储
  • 实现敏感词过滤

Day 5业务功能开发

  • 实现礼物打赏消息
  • 实现系统通知
  • 实现消息已读
  • 实现历史消息查询

Day 6Android客户端对接

  • 实现WebSocket连接
  • 实现消息收发UI
  • 实现弹幕显示
  • 实现礼物动画

Day 7测试与优化

  • 功能测试
  • 压力测试JMeter
  • 性能优化
  • 部署上线

九、接口设计

9.1 WebSocket接口

连接地址

ws://domain/ws?token=xxx

客户端发送消息格式

{
  "action": "sendMessage|sendBarrage|enterRoom|leaveRoom|heartbeat",
  "data": {
    // 具体数据
  }
}

服务端推送消息格式

{
  "type": "message|barrage|gift|system|notification",
  "data": {
    // 具体数据
  }
}

9.2 HTTP接口

用户认证

POST /api/auth/login
Body: {
  "username": "user123",
  "password": "xxx"
}
Response: {
  "code": 200,
  "data": {
    "token": "jwt_token",
    "userId": 123,
    "username": "user123",
    "nickname": "张三",
    "avatar": "xxx"
  }
}

好友相关接口

获取好友列表

GET /api/friend/list
Response: {
  "code": 200,
  "data": [
    {
      "friendId": 123,
      "username": "user123",
      "nickname": "张三",
      "avatar": "xxx",
      "remark": "备注名",
      "online": true,
      "lastOnlineTime": "2024-12-25 10:00:00"
    }
  ]
}

发送好友申请

POST /api/friend/request
Body: {
  "toUserId": 123,
  "message": "你好,可以加个好友吗?"
}
Response: {
  "code": 200,
  "message": "申请已发送"
}

获取好友申请列表

GET /api/friend/requests?status=0
Response: {
  "code": 200,
  "data": [
    {
      "requestId": 1,
      "fromUserId": 456,
      "username": "user456",
      "nickname": "李四",
      "avatar": "xxx",
      "message": "你好",
      "status": 0,
      "createdAt": "2024-12-25 10:00:00"
    }
  ]
}

处理好友申请

POST /api/friend/handle
Body: {
  "requestId": 1,
  "accept": true
}
Response: {
  "code": 200,
  "message": "已同意好友申请"
}

删除好友

DELETE /api/friend/{friendId}
Response: {
  "code": 200,
  "message": "已删除好友"
}

会话相关接口

获取会话列表

GET /api/conversation/list
Response: {
  "code": 200,
  "data": [
    {
      "conversationId": 1,
      "type": 1,
      "targetId": 123,
      "targetName": "张三",
      "targetAvatar": "xxx",
      "lastMessage": "你好",
      "lastMessageType": "text",
      "lastTime": "2024-12-25 10:00:00",
      "unreadCount": 3,
      "online": true
    }
  ]
}

删除会话

DELETE /api/conversation/{conversationId}
Response: {
  "code": 200,
  "message": "会话已删除"
}

消息相关接口

获取历史消息

GET /api/message/history?targetId=123&pageSize=20&lastMsgId=xxx
Response: {
  "code": 200,
  "data": {
    "messages": [
      {
        "msgId": "msg_001",
        "msgType": "text",
        "fromUserId": 456,
        "toUserId": 123,
        "content": "你好",
        "extra": {},
        "status": 1,
        "isRead": 1,
        "createdAt": "2024-12-25 10:00:00"
      }
    ],
    "hasMore": true
  }
}

上传图片

POST /api/upload/image
Content-Type: multipart/form-data
Body: file=xxx
Response: {
  "code": 200,
  "data": {
    "url": "https://xxx.com/image.jpg",
    "thumbnail": "https://xxx.com/image_thumb.jpg",
    "width": 1080,
    "height": 1920,
    "size": 102400
  }
}

上传语音

POST /api/upload/voice
Content-Type: multipart/form-data
Body: file=xxx
Response: {
  "code": 200,
  "data": {
    "url": "https://xxx.com/voice.mp3",
    "duration": 15,
    "size": 51200
  }
}

上传视频

POST /api/upload/video
Content-Type: multipart/form-data
Body: file=xxx
Response: {
  "code": 200,
  "data": {
    "url": "https://xxx.com/video.mp4",
    "cover": "https://xxx.com/cover.jpg",
    "duration": 20,
    "width": 720,
    "height": 1280,
    "size": 5242880
  }
}

发送图片消息

POST /api/message/sendImage
Body: {
  "toUserId": 123,
  "imageUrl": "xxx",
  "thumbnail": "xxx",
  "width": 1080,
  "height": 1920
}
Response: {
  "code": 200,
  "data": {
    "msgId": "msg_001"
  }
}

标记消息已读

POST /api/message/markRead
Body: {
  "conversationId": 1,
  "lastMsgId": "msg_456"
}
Response: {
  "code": 200,
  "message": "已标记为已读"
}

撤回消息

POST /api/message/recall
Body: {
  "msgId": "msg_123"
}
Response: {
  "code": 200,
  "message": "消息已撤回"
}

获取未读消息数

GET /api/message/unreadCount
Response: {
  "code": 200,
  "data": {
    "totalUnread": 15,
    "conversations": [
      {"conversationId": 1, "unread": 5},
      {"conversationId": 2, "unread": 10}
    ]
  }
}

礼物相关接口

获取礼物列表

GET /api/gift/list
Response: {
  "code": 200,
  "data": [
    {
      "giftId": 1,
      "name": "玫瑰",
      "icon": "xxx",
      "price": 10,
      "animation": "rose_animation"
    }
  ]
}

私聊送礼

POST /api/gift/sendPrivate
Body: {
  "toUserId": 123,
  "giftId": 1,
  "count": 1,
  "message": "送你一朵玫瑰"
}
Response: {
  "code": 200,
  "data": {
    "recordId": 1,
    "balance": 990
  }
}

直播间送礼

POST /api/gift/sendLive
Body: {
  "roomId": "room_001",
  "anchorId": 456,
  "giftId": 1,
  "count": 1
}
Response: {
  "code": 200,
  "data": {
    "recordId": 1,
    "balance": 990
  }
}

获取礼物记录

GET /api/gift/records?type=send&pageSize=20&page=1
Response: {
  "code": 200,
  "data": {
    "records": [
      {
        "recordId": 1,
        "fromUserId": 123,
        "toUserId": 456,
        "giftName": "玫瑰",
        "count": 1,
        "totalPrice": 10,
        "scene": "chat",
        "createdAt": "2024-12-25 10:00:00"
      }
    ],
    "total": 100
  }
}

通知相关接口

获取通知列表

GET /api/notification/list?type=all&pageSize=20&page=1
Response: {
  "code": 200,
  "data": [
    {
      "notificationId": 1,
      "type": "like",
      "fromUserId": 456,
      "fromUsername": "张三",
      "fromAvatar": "xxx",
      "content": "赞了你的作品",
      "targetType": "work",
      "targetId": 123,
      "isRead": 0,
      "createdAt": "2024-12-25 10:00:00"
    }
  ]
}

标记通知已读

POST /api/notification/markRead
Body: {
  "notificationIds": [1, 2, 3]
}
Response: {
  "code": 200,
  "message": "已标记为已读"
}

获取未读通知数

GET /api/notification/unreadCount
Response: {
  "code": 200,
  "data": {
    "like": 5,
    "comment": 3,
    "follow": 2,
    "system": 1,
    "total": 11
  }
}

十、安全方案

10.1 认证鉴权

  • 使用JWT token认证
  • Token有效期7天
  • 刷新Token机制

10.2 消息安全

  • 敏感词过滤(本地词库)
  • 消息内容长度限制500字符
  • 图片内容审核(接入第三方)

10.3 防刷机制

  • 消息发送频率限制
  • IP黑名单
  • 用户封禁机制

10.4 数据安全

  • WebSocket使用wss加密
  • 数据库密码加密存储
  • 敏感信息脱敏

十一、监控与运维

11.1 监控指标

  • 在线用户数
  • 消息发送量QPS
  • 接口响应时间
  • 服务器CPU/内存/网络

11.2 日志管理

  • 使用SLF4J + Logback
  • 日志分级ERROR、WARN、INFO
  • 日志文件按天切割
  • 保留30天日志

11.3 告警机制

  • 服务宕机告警
  • 接口异常告警
  • 资源使用告警

十二、成本预估

12.1 服务器成本

  • 阿里云ECS 4核8G约300元/月
  • 带宽5M约50元/月
  • 总计约350元/月

12.2 开发成本

  • 后端开发3人天
  • Android开发2人天
  • 测试1人天
  • 总计6人天

12.3 第三方服务(可选)

  • 图片审核:按量计费
  • 短信通知:按量计费
  • CDN加速按流量计费

十三、风险与应对

13.1 技术风险

风险: 单机性能瓶颈 应对: 提前设计水平扩展方案,预留扩展接口

风险: 消息丢失 应对: 实现消息ACK机制离线消息队列

风险: 直播间消息风暴 应对: 消息限流、降级策略

13.2 业务风险

风险: 用户量超预期 应对: 快速扩容方案,提前准备服务器

风险: 恶意刷屏 应对: 频率限制、封禁机制


十四、后续优化方向

14.1 功能优化

  • 消息撤回
  • 消息转发
  • @提醒功能
  • 表情包支持
  • 语音/视频通话

14.2 性能优化

  • 引入消息队列RabbitMQ/Kafka
  • 数据库分库分表
  • 引入ElasticSearch消息搜索
  • CDN加速图片、语音

14.3 架构优化

  • 微服务拆分
  • 服务注册与发现Nacos
  • 分布式链路追踪SkyWalking
  • 容器化部署Docker + K8s

附录

A. 参考资料

B. 开源方案参考

  • Netty-SocketIOJava WebSocket框架
  • t-io国产高性能IM框架
  • OpenIM开源IM解决方案

C. 敏感词库

  • 使用DFA算法实现高效过滤
  • 词库来源GitHub开源项目

文档版本: v1.0 编写日期: 2024-12-25 适用范围: 1-10万用户规模的直播IM系统