消息推送是企业信息系统中提升用户体验的关键功能。本文将介绍 IMS 系统中消息推送的整体设计方案。
消息推送的场景需求
IMS 系统中的消息推送主要覆盖以下场景:
- 审批通知 - 待审批事项自动推送给审批人
- 任务提醒 - 截止时间临近时提醒任务负责人
- 系统公告 - 重要通知全员推送
- 数据变更 - 关联数据更新时通知相关人员
- 即时通讯 - 消息提醒与未读计数
整体架构设计
消息推送系统采用分层架构:
- 接入层 - WebSocket 长连接 + HTTP 短连接
- 路由层 - 消息分发与用户路由
- 存储层 - 消息持久化与离线消息
- 推送层 - 实际推送通道(APP 推送、邮件、短信)
WebSocket 实时推送
实现基于 WebSocket 的实时消息推送:
websocket-server.js
// 消息推送服务 const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); // 用户连接管理 const userConnections = new Map(); // userId -> WebSocket wss.on('connection', (ws, req) => { // 从 URL 或 Token 获取用户 ID const userId = getUserIdFromRequest(req); userConnections.set(userId, ws); console.log(`用户 ${userId} 连接`); // 心跳保活 ws.on('ping', () => ws.pong()); // 断开连接 ws.on('close', () => { userConnections.delete(userId); console.log(`用户 ${userId} 断开`); }); // 接收客户端消息 ws.on('message', (data) => { const msg = JSON.parse(data); handleClientMessage(userId, msg); }); }); // 推送消息给指定用户 function pushToUser(userId, message) { const ws = userConnections.get(userId); if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify(message)); return true; } return false; } // 广播消息给所有在线用户 function broadcast(message) { userConnections.forEach((ws, userId) => { pushToUser(userId, message); }); }
消息类型定义
统一消息格式,便于前端处理:
message-types.js
// 消息类型枚举 const MessageType = { NOTIFICATION: 'notification', // 系统通知 APPROVAL: 'approval', // 审批提醒 TASK: 'task', // 任务提醒 CHAT: 'chat', // 即时消息 SYSTEM: 'system' // 系统公告 }; // 消息格式 const MessageSchema = { id: '消息唯一ID', type: '消息类型', title: '消息标题', content: '消息内容', sender: '发送者ID', receivers: ['接收者ID列表'], priority: '优先级: high/normal/low', action: { url: '点击跳转链接', method: 'POST/GET' }, createdAt: '创建时间', expireAt: '过期时间' };
消息存储设计
使用数据库存储消息,支持离线消息:
message-storage.js
// 消息存储服务 class MessageStore { async save(message) { // 存储消息到数据库 const sql = ` INSERT INTO messages (id, type, title, content, sender, priority, created_at, expire_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) `; await db.execute(sql, [ message.id, message.type, message.title, message.content, message.sender, message.priority, message.createdAt, message.expireAt ]); // 存储接收者关系 for (const receiverId of message.receivers) { await db.execute( `INSERT INTO message_receivers (message_id, user_id, is_read, read_at) VALUES (?, ?, 0, NULL)`, [message.id, receiverId] ); } } async getUnreadCount(userId) { const sql = ` SELECT COUNT(*) as count FROM message_receivers WHERE user_id = ? AND is_read = 0 `; const [row] = await db.execute(sql, [userId]); return row.count; } async markAsRead(messageId, userId) { await db.execute( `UPDATE message_receivers SET is_read = 1, read_at = NOW() WHERE message_id = ? AND user_id = ?`, [messageId, userId] ); } }
消息推送策略
根据消息类型和用户设置选择推送通道:
push-strategy.js
// 推送策略 class PushStrategy { async send(message, userId) { // 获取用户通知设置 const settings = await getUserSettings(userId); // 1. WebSocket 在线推送 const pushed = pushToUser(userId, message); // 2. 离线消息存储 if (!pushed) { await messageStore.save(message); } // 3. 根据设置决定是否发送邮件 if (settings.emailNotify && message.priority === 'high') { await sendEmail(userId, message); } // 4. APP 推送(移动端) if (settings.appNotify) { await sendAppPush(userId, message); } } }
前端接收处理
前端使用 EventSource 或 WebSocket 接收消息:
message-client.js
// 前端消息接收 class MessageClient { constructor() { this.ws = null; this.reconnectDelay = 3000; } connect() { this.ws = new WebSocket(`wss://${location.host}/ws`); this.ws.onmessage = (event) => { const message = JSON.parse(event.data); this.handleMessage(message); }; this.ws.onclose = () => { setTimeout(()=>this.connect(), this.reconnectDelay); }; } handleMessage(message) { // 更新未读计数 updateBadgeCount(); // 显示通知 if (message.type === 'notification') { showToast(message.title, message.content); } // 更新消息列表 prependToList(message); } }
总结
IMS 消息推送系统通过 WebSocket 实现实时推送,结合离线消息存储和多通道推送策略,确保用户能够及时收到重要通知。同时需要做好消息去重、限流等安全措施。