站内信消息功能解决方案
站内信消息功能解决方案
在中大型网站开发中,站内信、系统通知、用户私信是核心基础功能,既要保证实时性、稳定性,也要兼顾架构的可扩展性和运维便捷性。结合之前的高频疑问(技术选型、端口使用、内外网区分等),梳理一套企业级落地解决方案,覆盖从需求到部署的全流程,重点补充大数据量、高并发场景下MQ的应用细节,新手也能直接参考落地。
一、核心需求明确(避免过度设计)
先明确功能边界,避免技术选型冗余,中大型网站消息功能核心需求通常分为3类,其中大数据量高并发场景需额外关注消息峰值处理:
系统推送:订单状态、审核结果、系统公告、活动提醒等(单向推送,无需用户回复);高并发场景下可能出现批量推送(如活动通知、全员公告,峰值可达万级/秒);
用户私信:用户之间的双向聊天、留言(需要实时双向通信);高并发场景下需处理消息瞬时峰值(如热门活动互动、用户集中聊天);
基础交互:未读红点提示、消息列表分页、已读/全部已读、消息删除、历史消息查询;高并发下需保证查询性能,避免卡顿。
二、核心技术选型(中大型项目首选)
技术选型核心原则:优先轻量、兼容现有架构、便于扩容,拒绝过度设计,根据功能场景拆分技术方案,重点强化大数据量高并发场景下的MQ选型与应用:
1. 实时通信技术(核心重点)
按功能场景拆分,避免单一技术承载所有需求,降低雪崩风险:
系统通知/站内信(单向推送):首选 SSE(Server-Sent Events)
优势:基于HTTP协议,开发简单、资源占用低、浏览器原生支持自动重连,无需额外维护复杂逻辑;
适用场景:仅服务器向用户推送消息,无需用户反向发送数据(如订单提醒、公告推送);高并发场景下可配合MQ实现消息削峰,避免SSE服务被瞬时峰值压垮。
用户私信/双向聊天:选用 WebSocket
优势:全双工通信,低延迟,支持文本、二进制数据,适配双向实时交互场景;
注意:仅在需要双向通信时使用,单纯站内信无需上WebSocket,避免资源浪费;高并发聊天场景下,需通过MQ同步离线消息、群聊消息,保证消息不丢失、不重复。
降级方案:小型模块/非核心场景(如后台管理通知),可选用 HTTP 短轮询(3~5秒一次请求),开发成本最低,无需维护长连接;高并发峰值时,可作为SSE/WebSocket的降级方案,避免服务崩溃。
2. 存储与中间件选型(重点补充MQ高并发处理)
结合中大型项目分布式、高并发特点,选型如下,重点强化MQ在大数据量场景下的应用,解决消息峰值、消息同步、容错等核心问题:
数据存储:MySQL(主存储,存储消息明细、用户消息关联关系)+ Redis(缓存,存储未读消息数、在线用户连接状态、消息幂等标识);高并发场景下,MySQL需做分库分表,Redis需做集群部署,避免存储瓶颈;
分布式同步与高并发处理(核心:MQ选型与应用):
选型建议:轻量场景用 Redis Pub/Sub(适用于消息实时性要求高、无需持久化的场景,如在线用户消息推送);大数据量、高并发、高可靠场景首选 RabbitMQ/RocketMQ(适用于批量推送、离线消息、消息重试,支持流量削峰、死信队列,避免消息丢失);
核心作用:解决多服务实例消息广播、大数据量瞬时峰值削峰、消息异步处理、离线消息缓存等问题,保证高并发场景下消息推送的稳定性和可靠性;
MQ集群配置:生产环境需部署MQ集群(至少3节点),开启消息持久化、主从复制,避免单点故障;根据消息峰值调整队列分区,提高消息处理吞吐量。
网关层:Spring Cloud Gateway 或 Nginx,统一入口,实现路由转发、负载均衡、协议升级(WebSocket);高并发场景下,网关需做集群部署,配置限流、熔断策略,避免网关成为瓶颈。
三、端口规划(重点:内外网区分)
这是之前高频疑问的核心,明确结论:外网统一端口,内网按服务拆分端口,兼顾安全、运维便捷性和服务隔离,补充MQ服务的端口规划:
1. 外网端口(用户侧)
无需额外开任何端口,所有流量统一收敛到标准端口:
HTTP:80端口(建议跳转至HTTPS);
HTTPS:443端口(生产环境首选,统一入口);
所有功能(普通接口、SSE、WebSocket)共用以上端口,通过路径区分(如 /api/* 业务接口、/sse/* 推送接口、/ws/* 聊天接口)。
优势:减少防火墙配置、证书管理成本,符合企业级安全规范,用户无感知多服务。
2. 内网端口(服务侧,中大型项目必做)
内部微服务必须按服务拆分端口,实现资源隔离、独立扩容,避免互相拖累,推荐端口规划如下(可按需调整),补充MQ集群相关端口:
| 服务类型 | 内网端口 | 备注 |
|---|---|---|
| 普通业务服务(核心业务) | 8080 | 处理用户登录、订单、个人中心等基础业务,高并发下可集群部署 |
| SSE消息服务(站内信/系统通知) | 8085 | 单独承载长连接,订阅MQ消息,避免占用业务服务资源,高并发下可横向扩容 |
| WebSocket聊天服务(用户私信) | 8086 | 独立维护双向长连接,订阅MQ离线消息,便于单独扩容、监控 |
| Redis服务(集群) | 6379(主)、6380(从) | 缓存未读消息数、在线连接状态、消息幂等标识,高并发下保障查询性能 |
| MQ服务(RabbitMQ集群) | 5672(通信端口)、15672(管理端口) | 分布式消息同步、削峰填谷,处理大数据量瞬时消息峰值,开启持久化和集群容错 |
| MQ服务(RocketMQ集群) | 9876(Namesrv端口)、10911(Broker端口) | 适用于超大数据量场景(十万级/秒峰值),支持分区队列、事务消息,高吞吐、高可靠 |
关键注意:内网端口仅用于内部服务通信,绝不对外暴露,所有外网请求均通过网关(443端口)转发;MQ服务的管理端口(如15672)需限制内网访问,避免安全风险。
四、架构设计(中大型项目标准落地版,强化高并发处理)
1. 整体架构流程图(补充MQ高并发流转)
用户 → 外网443端口 → 网关(路由转发+限流熔断) → 各内网服务 → MQ集群(削峰/同步) → 存储/中间件
具体拆分,重点补充MQ在高并发场景下的流转:
用户侧:仅访问域名(如 https://xxx.com),无需关注任何端口、服务拆分;
网关层:统一接收所有请求,按路径路由到对应内网服务,配置限流策略(如每秒限制1万请求),避免高并发请求压垮后端服务;
服务层:各服务独立部署、独立端口,通过Redis/MQ实现数据同步;高并发场景下,业务服务发送消息后立即返回,消息异步投递到MQ,由SSE/WebSocket服务异步消费,实现削峰;
MQ层:接收业务服务投递的消息,按消息类型分队列存储(如系统通知队列、私信队列),支持消息持久化、重试、死信队列,避免消息丢失;
存储层:MySQL存储消息明细(分库分表),Redis缓存热点数据,保证查询性能。
2. 核心业务流程(以用户接收站内信为例,补充MQ高并发处理)
系统/用户发起发消息请求(高并发场景下可能是批量请求,如全员公告),调用 /msg/send 接口(业务服务8080端口);
业务服务接收请求后,先做参数校验、幂等性判断(通过Redis缓存消息ID,避免重复发送),然后将消息写入MySQL,同时异步投递消息到MQ对应队列(如system_notice_queue),立即返回成功,无需等待消息推送完成(削峰核心步骤);
SSE服务(8085端口)作为MQ消费者,持续订阅system_notice_queue队列,获取消息后,查询接收人是否在线(Redis缓存在线状态);
接收人在线:SSE服务通过长连接将消息推送到用户浏览器,触发弹窗/红点提醒;推送失败则将消息重新投递到MQ重试队列,最多重试3次;
接收人不在线:SSE服务将消息标记为“离线消息”,更新到MySQL,用户下次登录时,前端通过接口拉取消息列表,展示未读红点;
用户操作(已读、删除):调用对应接口,更新MySQL状态和Redis缓存,同时将操作消息投递到MQ,同步更新各服务状态。
3. 关键设计要点(中大型项目必考虑,重点补充高并发/MQ相关)
服务隔离:SSE、WebSocket长连接服务必须与普通业务服务拆分,避免长连接占用业务线程,导致业务雪崩;MQ消费者服务独立部署,与生产者隔离,避免生产者故障影响消费者;
扩容能力:SSE、WebSocket服务支持集群部署,通过Redis维护在线用户连接映射,实现负载均衡;MQ队列支持分区,消费者集群部署,提高消息处理吞吐量,应对大数据量峰值;
容错机制:
长连接中断时,SSE依赖浏览器原生重连,WebSocket手动实现心跳+重连逻辑;
消息推送失败时,通过MQ重试队列重试(最多3次),重试失败则投递到死信队列,后续人工处理,避免消息丢失;
MQ集群故障时,业务服务将消息暂存到本地磁盘(降级方案),待MQ恢复后批量投递,避免消息丢失;
幂等性保障:通过Redis缓存消息ID,避免重复发送、重复消费(如用户重复接收同一条消息)。
监控告警:单独监控各服务的连接数、内存占用、消息推送成功率;重点监控MQ集群的队列堆积量、消息消费速率、重试次数,当队列堆积超过阈值(如1万条)、消费速率异常时,及时告警,避免消息堆积导致服务雪崩;
高并发优化:消息批量投递、批量消费(减少MQ交互次数);Redis缓存热点消息(如高频通知),减少MySQL查询压力;MQ队列按消息类型拆分,避免单一队列堆积;业务服务做请求限流,避免瞬时峰值压垮服务。
五、必备接口设计(直接抄用,补充MQ相关接口)
所有接口统一前缀,共用外网443端口,按路径区分服务,接口返回格式统一(JSON),补充高并发场景下MQ相关的管理接口:
1. 基础消息接口(HTTP接口,业务服务8080端口)
GET /api/msg/list?page=1&size=10:获取消息列表(分页,支持筛选已读/未读);
GET /api/msg/unread/count:获取未读消息数量(用于红点提示);
POST /api/msg/read/{msgId}:单条消息标为已读;
POST /api/msg/read/all:全部消息标为已读;
DELETE /api/msg/{msgId}:删除单条消息;
POST /api/msg/send:发送消息(系统/用户调用,支持单发/群发);高并发场景下支持批量发送,接口内部异步投递MQ;
POST /api/msg/batch/send:批量发送消息(如全员公告),专门适配大数据量场景,支持一次发送1000条以上消息,异步投递MQ,避免接口超时。
2. 实时推送接口(长连接接口)
SSE接口:GET /sse/msg,用户登录后建立长连接,接收系统通知/站内信;高并发场景下支持连接复用,减少服务压力;
WebSocket接口:WS /ws/chat,用户进入私信页面后建立连接,实现双向聊天;支持离线消息拉取(从MQ/MySQL拉取未读消息)。
3. MQ管理接口(运维/监控用,内网访问)
GET /api/mq/queue/status:查询MQ队列状态(堆积量、消费速率、重试次数);
POST /api/mq/queue/clear:清理MQ队列堆积消息(手动运维用);
GET /api/mq/dead/msg:查询死信队列消息,用于排查消息推送失败问题。
六、数据库表设计(核心3张表,适配中大型项目,补充高并发优化)
避免冗余,聚焦核心字段,支持扩展,补充高并发场景下的字段设计(如幂等标识、消息状态):
1. 消息主表(message)
存储消息核心信息,支持多类型消息,适配高并发批量推送:
id:主键(自增/雪花ID);
sender_id:发送人ID(0表示系统);
receiver_id:接收人ID(多接收人用逗号分隔,或单独建群发关联表;批量推送时可存储接收人群组ID);
title:消息标题(系统通知必填,私信可选);
content:消息内容(支持HTML/Markdown,按需配置);
msg_type:消息类型(1-系统通知、2-订单提醒、3-私信、4-审核提醒);
create_time:创建时间;
is_delete:是否删除(逻辑删除,0-未删除,1-已删除);
msg_id:消息唯一标识(UUID),用于MQ消息幂等性判断,避免重复发送/消费;
push_status:推送状态(0-待推送、1-推送中、2-推送成功、3-推送失败),用于监控消息推送情况;
retry_count:重试次数(默认0,最多3次),用于MQ消息重试统计。
2. 用户消息关联表(user_message)
关联用户与消息,记录用户对消息的操作状态(核心表),适配高并发查询:
id:主键;
user_id:用户ID;
msg_id:消息ID(关联message表);
is_read:是否已读(0-未读,1-已读);
delete_time:删除时间(逻辑删除,null表示未删除);
read_time:已读时间(null表示未读);
receive_time:消息接收时间(用于统计消息推送延迟,高并发场景下监控推送效率)。
3. 消息类型字典表(msg_type_dict)
用于消息类型管理,便于扩展:
id:主键;
type_code:类型编码(与message表msg_type对应);
type_name:类型名称;
remark:备注(如“订单状态变更提醒”);
mq_queue:对应MQ队列名称(如system_notice_queue、chat_queue),用于消息按类型投递到对应队列。
七、常见问题与避坑指南(补充高并发/MQ相关)
坑1:将SSE/WebSocket与业务服务混部署,导致业务高峰时长连接雪崩 → 解决方案:强制拆分服务、独立端口,实现资源隔离;
坑2:外网暴露多个端口,增加安全风险和运维成本 → 解决方案:所有外网流量收敛到443端口,网关统一转发;
坑3:未做长连接重连机制,导致用户离线后无法接收消息 → 解决方案:SSE依赖浏览器原生重连,WebSocket手动实现心跳+重连;
坑4:分布式环境下,多服务实例无法同步消息 → 解决方案:引入Redis Pub/Sub或MQ,实现消息广播;高并发场景下优先用MQ,避免Redis Pub/Sub消息丢失;
坑5:消息存储未做分表,数据量过大时查询缓慢 → 解决方案:按时间分表(如每月一张表),配合Redis缓存热点数据;
坑6:高并发场景下,MQ队列堆积严重,导致消息推送延迟 → 解决方案:MQ队列分区、消费者集群部署;优化消息消费逻辑,避免消费阻塞;设置队列堆积阈值,及时告警;
坑7:未做消息幂等性处理,导致用户重复接收消息 → 解决方案:通过Redis缓存消息唯一标识(msg_id),生产者投递前校验、消费者消费前校验,避免重复发送/消费;
坑8:MQ单点故障,导致消息无法投递 → 解决方案:部署MQ集群(至少3节点),开启主从复制、消息持久化;业务服务增加降级方案,暂存消息到本地磁盘,待MQ恢复后批量投递;
坑9:批量推送时,接口超时 → 解决方案:接口内部异步投递MQ,立即返回成功;批量消息分批次投递(如每100条一批),避免单次投递过多导致超时。
八、总结
中大型网站站内信/消息功能,核心是“拆分合理、隔离到位、端口统一”,而大数据量、高并发场景下,核心是通过MQ实现“削峰填谷、异步处理、容错保障”:
技术选型:单向推送用SSE,双向聊天用WebSocket,大数据量高并发场景首选RabbitMQ/RocketMQ,不盲目追求复杂技术;
端口规划:外网统一443,内网按服务拆分端口,MQ服务端口仅内网暴露,兼顾安全与运维;
架构设计:微服务拆分,网关收敛流量,Redis/MQ保障分布式同步;高并发场景下,通过MQ异步处理消息、削峰填谷,避免服务雪崩;
落地重点:服务隔离、容错机制、监控告警,补充MQ队列管理、幂等性处理、批量推送优化,确保大数据量高并发场景下的稳定性和可靠性。
这套方案适配绝大多数中大型网站,可根据自身业务体量(如用户量、消息峰值)灵活调整,既保证落地效率,也为后续扩容预留空间;尤其针对大数据量高并发场景,MQ的合理应用的是保障消息功能稳定运行的核心。