·4 min read
WebSocket 实时通信架构设计
分享客服聊天系统中 WebSocket 实时通信的架构设计与实现经验。
#WebSocket#实时通信#Vue#Node.js
WebSocket 实时通信架构设计
在客服聊天系统项目中,我负责设计和实现了基于 WebSocket 的实时通信架构。今天分享一下核心设计思路。
系统架构
访客端 ←→ WebSocket Server ←→ 客服端
↓
消息队列 (Redis)
↓
数据持久化 (MySQL)
核心功能实现
1. 连接管理
// WebSocket 连接管理
class ConnectionManager {
constructor() {
this.connections = new Map() // userId -> ws
}
add(userId, ws) {
this.connections.set(userId, ws)
}
remove(userId) {
this.connections.delete(userId)
}
sendTo(userId, message) {
const ws = this.connections.get(userId)
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(message))
}
}
}
2. 消息类型设计
interface Message {
type: 'chat' | 'system' | 'transfer' | 'close'
from: string
to: string
content: string
timestamp: number
}
3. Vuex 状态管理
// store/modules/chat.js
export default {
state: {
conversations: [],
currentConversation: null,
messages: []
},
actions: {
// 接收新消息
receiveMessage({ commit, state }, message) {
commit('ADD_MESSAGE', message)
// 更新对话列表
const conversation = state.conversations.find(
c => c.id === message.conversationId
)
if (conversation) {
conversation.lastMessage = message
conversation.unread++
}
},
// 发送消息
async sendMessage({ commit }, message) {
commit('ADD_MESSAGE', { ...message, sending: true })
try {
await socket.emit('send-message', message)
commit('UPDATE_MESSAGE_STATUS', { id: message.id, status: 'sent' })
} catch (error) {
commit('UPDATE_MESSAGE_STATUS', { id: message.id, status: 'failed' })
}
}
}
}
关键场景处理
1. 断线重连
class SocketClient {
constructor() {
this.reconnectAttempts = 0
this.maxReconnectAttempts = 5
}
connect() {
this.ws = new WebSocket(this.url)
this.ws.onclose = () => {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
setTimeout(() => {
this.reconnectAttempts++
this.connect()
}, 3000 * this.reconnectAttempts)
}
}
this.ws.onopen = () => {
this.reconnectAttempts = 0
}
}
}
2. 心跳检测
// 心跳保活
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }))
}
}, 30000)
3. 消息确认机制
// 消息回执
const pendingMessages = new Map()
function sendWithAck(message) {
return new Promise((resolve, reject) => {
pendingMessages.set(message.id, { resolve, reject })
ws.send(JSON.stringify(message))
// 超时处理
setTimeout(() => {
if (pendingMessages.has(message.id)) {
pendingMessages.delete(message.id)
reject(new Error('Timeout'))
}
}, 10000)
})
}
// 收到回执
ws.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.type === 'ack' && pendingMessages.has(data.messageId)) {
pendingMessages.get(data.messageId).resolve()
pendingMessages.delete(data.messageId)
}
}
性能优化
1. 消息分页加载
// 分页获取历史消息
async loadHistory(conversationId, page = 1) {
const messages = await api.getMessages({
conversationId,
page,
pageSize: 20
})
this.messages.unshift(...messages)
}
2. 虚拟列表渲染
对于大量消息的场景,使用虚拟列表优化性能:
<virtual-list
:items="messages"
:item-height="60"
v-slot="{ item }"
>
<message-item :message="item" />
</virtual-list>
总结
WebSocket 实时通信的关键点:
- 连接稳定性:断线重连、心跳保活
- 消息可靠性:确认机制、重试策略
- 状态管理:统一的状态管理避免数据不一致
- 性能优化:分页加载、虚拟列表
这套架构在实际项目中稳定运行,支持了日均数万次的会话量。
有问题欢迎交流!
感谢阅读!如有问题,欢迎交流讨论。
返回文章列表