Products
GG网络技术分享 2026-04-16 04:56 0
说实话, 很多小伙伴在写即时聊天功能时总是忍不住把数据库写入和消息推送绑在一起——后来啊就是用户点了“发送”,页面卡到转圈儿,甚至服务器直接抛异常。这不就是把一条信息塞进了拥堵的高速路,却忘了给它加个快递通道吗呃?
没耳听。 于是 我决定把 Spring Boot 3 与各种MQ玩个大杂烩,让聊天消息先飞到队列里再让后端慢慢地、稳稳地写进数据库。下面这篇“烂文”会把整个过程拆得稀巴烂,还顺手塞进几段乱七八糟的代码、表格和情绪。

解耦合——把「用户发送」和「消息持久化」分成两条平行线; 削峰填谷——高峰期来一堆消息, 队列里先排队,消费端慢慢吃; 容错弹性——即使数据库短暂挂掉,消息也不会丢,只会在队列里等,走捷径。。
| 消息队列 | 部署难度 | 吞吐量 | 持久化特性 | 适合场景 |
|---|---|---|---|---|
| RabbitMQ | 中等 | 10k~50k | 可靠持久化 + ACK 机制 | 聊天、 订单、日志收集 |
| ActiveMQ | 高 | 5k~20k | 事务+持久化可选 | 企业内部系统集成 |
| RocketMQ | 高 | 100k+ | 强一致性日志存储 | 金融、海量流式数据 |
| Kafka |
先拉一个带管理插件的 RabbitMQ 镜像:,蚌埠住了!
docker pull rabbitmq:4.1-management
docker run --name rabbitmq \
-p 5672:5672 -p 15672:15672 \
--restart always -d rabbitmq:4.1-management
# 注意:这里端口映射随意改,别跟本地 MySQL 冲突
Spring Boot 项目里加上依赖:
org.springframework.boot
spring-boot-starter-amqp
org.projectlombok
lombok
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
virtual-host: /
# 小技巧:如果想让容器外部访问,把 guest 改成 admin,免得被限制
#
myapp:
chat:
queue-name: chat.message.queue # 随便起名
exchange-name: chat.message.ex # 随便起名
routing-key: chat.message.key # 随便起名
# 配置完直接启动吧,不要纠结是否符合最佳实践 🙈
logging:
level:
org.springframework.amqp: DEBUG # 想看细节就打开它
DROP TABLE IF EXISTS `chat_message`;
CREATE TABLE `chat_message` (
`id` varchar NOT NULL COMMENT '主键 UUID',
`sender_id` varchar NOT NULL COMMENT '发送者 ID',
`receiver_id` varchar NOT NULL COMMENT '接收者 ID',
`receiver_type` int NULL DEFAULT NULL COMMENT '接收者类型 ',
`msg` varchar NOT NULL COMMENT '文字内容',
`msg_type` int NOT NULL COMMENT '文字/图片/视频等枚举',
`chat_time` datetime NOT NULL COMMENT '发送时间',
`is_read` tinyint DEFAULT 0 COMMENT '是否已读',
PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天记录表';
-- 注意这里没有索引!如果你想查询历史,请自行加上!😅
@RestController
@RequestMapping
public class ChatController {
@Resource
private AmqpTemplate amqpTemplate;
@PostMapping
public ResponseEntity send {
// 构造业务对象 —— 实际项目中请使用 Lombok + Builder...
ChatMsg msg = new ChatMsg;
msg.setId.toString.replace);
msg.setSenderId);
msg.setReceiverId);
msg.setMsg);
msg.setMsgType; // 文本
// 把对象序列化成 JSON 再发到 MQ
String json = new com.fasterxml.jackson.databind.ObjectMapper
.writeValueAsString;
// 发往交换机+路由键
amqpTemplate.convertAndSend(
"${myapp.chat.exchange-name}",
"${myapp.chat.routing-key}",
json);
// 响应前端:已经成功投递到 MQ!
return ResponseEntity.ok;
}
}
Demand feedback