无Redis实时客服系统实现文档

无Redis实时客服系统实现文档

无Redis实时客服系统实现文档

📋 项目概述

本项目实现了一个基于 Node.js + MongoDB 的实时客服系统,无需 Redis,通过 Socket.IO 实现实时通信,使用 MongoDB 进行数据持久化。

🏗️ 系统架构

核心组件

  • 后端框架: Fastify (Node.js)

  • 数据库: MongoDB

  • 实时通信: Socket.IO

  • 前端框架: Handlebars + Tailwind CSS

  • 认证: Cookie-based 认证

架构特点

  • 无Redis依赖: 使用内存 Map 管理在线状态

  • 实时通信: WebSocket 双向通信

  • 数据持久化: MongoDB 存储聊天记录

  • 响应式设计: 现代化 UI 界面

📊 数据库设计

1. 客服表 (web_chat_agent)


{

  _id: ObjectId,

  username: String,        // 用户名

  password: String,        // 加密密码

  realName: String,        // 真实姓名

  email: String,          // 邮箱

  phone: String,          // 电话

  skills: Array,          // 技能标签

  maxConcurrent: Number,  // 最大并发数

  status: String,         // 状态: ONLINE/OFFLINE

  isActive: Boolean,      // 是否启用

  add_time: Number        // 创建时间

}

2. 聊天房间表 (web_chat_room)


{

  _id: ObjectId,

  customerId: String,     // 客户ID

  customerName: String,   // 客户姓名

  agentId: ObjectId,      // 客服ID (可选)

  status: String,         // 状态: WAITING/SERVING/CLOSED

  category: String,       // 咨询类别

  priority: String,       // 优先级: LOW/MEDIUM/HIGH

  createdAt: Number,      // 创建时间

  endedAt: Number,        // 结束时间 (可选)

  endReason: String       // 结束原因 (可选)

}

3. 聊天消息表 (web_chat_message)


{

  _id: ObjectId,

  roomId: ObjectId,       // 房间ID

  senderId: String,       // 发送者ID

  senderType: String,     // 发送者类型: CUSTOMER/AGENT

  content: String,        // 消息内容

  msgType: String,        // 消息类型: text

  createdAt: Number,      // 发送时间

  isSystem: Boolean       // 是否系统消息

}

4. 客服统计表 (web_chat_agent_stats)


{

  _id: ObjectId,

  agentId: ObjectId,      // 客服ID

  date: String,           // 统计日期

  totalSessions: Number,  // 总会话数

  avgResponseTime: Number, // 平均响应时间

  customerSatisfaction: Number // 客户满意度

}

🔧 核心实现

1. Socket.IO 管理器 (socketManager.ts)

内存状态管理


// 客服在线状态管理

const onlineAgents = new Map<string, {

    socketId: string;

    lastPing: number;

    currentRooms: string[];

}>();



// 房间连接管理

const roomConnections = new Map<string, {

    customerSocketId?: string;

    agentSocketId?: string;

}>();

主要事件处理

  • agent:login - 客服登录

  • customer:join - 客户加入房间

  • agent:join - 客服加入房间

  • agent:leave - 客服离开房间

  • msg:send - 发送消息

  • disconnect - 断开连接

2. 房间分配策略

原子操作分配


const result = await collection('web_chat_room').findOneAndUpdate(

    {

        _id: new ObjectId(roomId),

        status: 'WAITING'

    },

    {

        $set: {

            status: 'SERVING',

            agentId: new ObjectId(agentId)

        }

    },

    { returnDocument: 'after' }

);

实时通知机制


// 通知客户房间已分配

socketManager.notifyRoomAssigned(roomId, agentId);



// 通知所有客服有新房间

socketManager.notifyNewRoom(room);

3. 消息处理流程

消息发送

  1. 客户端发送 msg:send 事件

  2. 服务器保存到 MongoDB

  3. 广播 msg:new 事件给房间内所有用户

消息持久化


const message = {

    roomId: new ObjectId(data.roomId),

    senderId: data.senderId,

    senderType: data.senderType,

    content: data.content,

    msgType: 'text',

    createdAt: Date.now(),

    isSystem: false

};



await collection('web_chat_message').insertOne(message);

🎨 前端实现

1. 客户聊天页面 (customer_chat.hbs)

核心功能

  • 自动重连: 页面刷新后自动恢复会话

  • 实时消息: WebSocket 实时接收消息

  • 状态管理: 显示连接状态和聊天状态

  • 消息样式: 客户消息右对齐蓝色,客服消息左对齐绿色

关键代码


// 自动恢复会话

window.addEventListener('load', () => {

    const savedRoomId = localStorage.getItem('customerRoomId');

    if (savedRoomId) {

        checkRoomStatus();

    }

});



// 实时消息接收

socket.on('msg:new', (message) => {

    if (message.senderType === 'AGENT') {

        addMessage('客服', message.content);

    } else if (message.senderType === 'CUSTOMER') {

        addMessage('我', message.content);

    }

});

2. 客服工作台 (agent_dashboard.hbs)

核心功能

  • 多房间管理: 支持同时服务多个房间

  • 房间切换: 可以在不同房间间切换

  • 历史会话: 查看已结束的聊天记录

  • 实时通知: 新房间到达时实时提醒

关键代码


// 房间切换机制

async function switchToRoom(roomId) {

    // 离开当前房间

    if (currentRoomId && socket) {

        socket.emit('agent:leave', { roomId: currentRoomId, agentId: String(agentId) });

    }

    

    // 加入新房间

    socket.emit('agent:join', { roomId: roomId, agentId: String(agentId) });

    

    // 加载历史消息

    await loadRoomHistory(roomId);

}



// 实时新房间通知

socket.on('room:new', (room) => {

    addWaitingRoom(room);

});

🚀 部署和运行

1. 环境要求

  • Node.js >= 16

  • MongoDB >= 4.4

  • pnpm (推荐) 或 npm

2. 安装依赖


pnpm install

3. 启动开发服务器


pnpm run dev

4. 构建生产版本


pnpm run build

pnpm start

📱 访问路径

客户端

  • 客户聊天: http://localhost:3000/customer-chat

客服端

  • 客服登录: http://localhost:3000/agent/login

  • 客服注册: http://localhost:3000/agent/register

  • 客服工作台: http://localhost:3000/agent/dashboard

🔄 工作流程

1. 客户发起聊天

  1. 客户访问 /customer-chat

  2. 点击"开始聊天"按钮

  3. 系统创建聊天房间 (状态: WAITING)

  4. 客户进入等待状态

2. 客服接受聊天

  1. 客服登录工作台

  2. 在"等待中的房间"看到新房间

  3. 点击接受房间

  4. 系统分配房间给客服 (状态: SERVING)

  5. 客户收到通知,开始聊天

3. 实时聊天

  1. 双方通过 WebSocket 实时发送消息

  2. 消息保存到 MongoDB

  3. 支持表情、文本等消息类型

4. 结束聊天

  1. 客服点击"结束聊天"

  2. 系统更新房间状态 (状态: CLOSED)

  3. 聊天记录保存到历史会话

  4. 双方收到结束通知

🎯 技术亮点

1. 无Redis架构

  • 使用内存 Map 管理在线状态

  • 减少系统复杂度

  • 降低部署成本

2. 原子操作

  • 使用 MongoDB findOneAndUpdate 确保房间分配的唯一性

  • 避免并发问题

3. 实时通信

  • Socket.IO 提供可靠的 WebSocket 连接

  • 自动重连机制

  • 房间级别的消息广播

4. 用户体验

  • 响应式设计

  • 现代化 UI

  • 流畅的动画效果

5. 数据持久化

  • 完整的聊天记录保存

  • 历史会话查询

  • 客服统计功能

🔧 扩展功能

1. 可扩展的功能

  • 文件上传

  • 语音消息

  • 视频通话

  • 客服评价系统

  • 智能分配算法

  • 多语言支持

2. 性能优化

  • 消息分页加载

  • 图片压缩

  • 连接池优化

  • 缓存策略

📝 总结

本系统成功实现了无Redis的实时客服系统,通过 Socket.IO 和 MongoDB 的组合,提供了完整的实时聊天功能。系统具有良好的扩展性和可维护性,可以作为企业级客服系统的基础框架。

核心优势:

  • ✅ 无需 Redis,降低部署复杂度

  • ✅ 实时通信,用户体验良好

  • ✅ 数据持久化,完整记录保存

  • ✅ 现代化 UI,界面美观

  • ✅ 代码清晰,易于维护和扩展


本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。

萧兮的博客https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/a6445dad-9c1e-469b-990d-5ecb868a92e6