1. 系统架构概述
本文介绍一个基于Netty框架构建的WebSocket实时消息推送系统,该系统采用异步非阻塞设计,支持高并发连接,并实现了事务感知的消息推送机制。
2. 核心组件设计
2.1 消息包装类
java
import lombok.Data;
/**
* WebSocket消息包装类
* 用于统一消息格式,支持多种数据类型
* @param type 消息类型标识:TEMP(温度数据)、ALARM(报警信息)、GPS(位置信息)
* @param data 实际业务数据对象
*/
@Data
public class WsMessage {
private String type;
private Object data;
public WsMessage(String type, Object data) {
this.type = type;
this.data = data;
}
}
2.2 Netty服务器配置
java
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Netty WebSocket服务器
* 负责初始化服务器配置、处理连接请求和消息转发
*/
@Slf4j
@Component
public class NettyServer {
private final int port = 9000; // WebSocket服务端口
/**
* 服务器启动方法
* 使用独立线程启动Netty服务,避免阻塞主线程
*/
@PostConstruct
public void start() {
new Thread(() -> {
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 接收连接线程组
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 处理业务线程组
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
// HTTP协议编解码器
pipeline.addLast(new HttpServerCodec());
// 支持大数据流传输
pipeline.addLast(new ChunkedWriteHandler());
// 聚合HTTP请求为完整报文
pipeline.addLast(new HttpObjectAggregator(65536));
// WebSocket协议处理器,指定连接路径
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
// 自定义业务处理器
pipeline.addLast(new NettyWebSocketHandler());
}
});
ChannelFuture future = bootstrap.bind(port).sync();
log.info("Netty WebSocket服务已启动,监听端口:{}", port);
future.channel().closeFuture().sync();
} catch (Exception e) {
log.error("Netty服务启动异常:", e);
} finally {
// 优雅关闭线程组
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}).start();
}
}
2.3 WebSocket消息处理器
java
import com.alibaba.fastjson2.JSON;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
/**
* WebSocket消息处理器
* 负责管理客户端连接、接收消息和广播推送
*/
public class NettyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
// 在线客户端连接池,使用全局事件执行器管理
private static final ChannelGroup CLIENTS = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
// 新连接加入时添加到连接池
CLIENTS.add(ctx.channel());
log.debug("客户端连接建立,当前连接数:{}", CLIENTS.size());
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
// 处理客户端消息(可用于心跳检测、身份验证等)
String message = frame.text();
log.debug("收到客户端消息:{}", message);
// 可在此处添加业务逻辑处理
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
// 连接断开时从连接池移除
CLIENTS.remove(ctx.channel());
log.debug("客户端连接断开,当前连接数:{}", CLIENTS.size());
}
/**
* 推送消息到所有客户端
* @param type 消息类型
* @param data 消息数据
*/
public static void pushMessage(String type, Object data) {
// 1. 构造标准消息格式
WsMessage message = new WsMessage(type, data);
// 2. 序列化为JSON字符串
String jsonMessage = JSON.toJSONString(message);
// 3. 广播推送到所有客户端
CLIENTS.writeAndFlush(new TextWebSocketFrame(jsonMessage));
log.debug("消息推送成功,类型:{},接收客户端数:{}", type, CLIENTS.size());
}
}
2.4 事务感知的消息推送器
java
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* 事务感知的消息推送器
* 确保消息推送与数据库事务的一致性
*/
@Component
public class TransactionalPusher {
/**
* 事务提交后推送消息
* 保证只有事务成功提交后才执行消息推送,避免数据不一致
*
* @param type 消息类型
* @param data 消息数据
*/
public void pushAfterCommit(String type, Object data) {
// 检查当前是否存在活跃事务
if (TransactionSynchronizationManager.isActualTransactionActive()) {
// 注册事务同步器,在事务提交后执行推送
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务提交成功后执行推送
NettyWebSocketHandler.pushMessage(type, data);
log.debug("事务提交后推送消息,类型:{}", type);
}
});
} else {
// 无事务环境直接推送
NettyWebSocketHandler.pushMessage(type, data);
log.debug("非事务环境推送消息,类型:{}", type);
}
}
}
3. 使用示例
3.1 业务层调用
java
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@Service
public class BusinessService {
@Resource
private TransactionalPusher transactionalPusher;
/**
* 业务方法示例
* 在需要推送WebSocket消息的地方调用推送器
*/
public void performBusinessOperation() {
// 业务逻辑处理...
// 推送实时消息
transactionalPusher.pushAfterCommit("info", "业务操作完成");
// 推送复杂对象
Map<String, Object> data = new HashMap<>();
data.put("id", 123);
data.put("status", "SUCCESS");
data.put("timestamp", System.currentTimeMillis());
transactionalPusher.pushAfterCommit("data_update", data);
}
}
4. 系统特性
4.1 技术优势
- 高性能:基于Netty的异步非阻塞架构,支持高并发连接
- 低延迟:事件驱动模型确保消息实时推送
- 事务一致性:消息推送与数据库事务同步,避免数据不一致
- 可扩展性:模块化设计,便于扩展新消息类型和处理逻辑
- 连接管理:自动维护客户端连接池,支持连接状态监控
4.2 应用场景
- 实时监控系统:设备状态、温度、压力等实时数据推送
- 在线协作:多用户实时协同操作
- 即时通讯:聊天消息、通知推送
- 金融交易:实时行情、交易结果通知
- 物联网:设备数据采集与指令下发
5. 系统特性与总结
5.1 技术优势
- 高性能:基于Netty的异步非阻塞架构,支持高并发连接
- 低延迟:事件驱动模型确保消息实时推送
- 事务一致性:消息推送与数据库事务同步,避免数据不一致
- 可扩展性:模块化设计,便于扩展新消息类型和处理逻辑
- 连接管理:自动维护客户端连接池,支持连接状态监控
5.2 客户端使用示例
javascript
// JavaScript客户端连接示例
const socket = new WebSocket('ws://localhost:9000/ws');
socket.onopen = () => {
console.log('WebSocket连接已建立');
};
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('收到消息:', message.type, message.data);
// 根据type处理不同类型的消息
switch(message.type) {
case 'TEMP':
// 处理温度数据
break;
case 'ALARM':
// 处理报警信息
break;
case 'GPS':
// 处理位置信息
break;
}
};
socket.onclose = () => {
console.log('WebSocket连接已关闭');
};
// 发送心跳保持连接
setInterval(() => {
if(socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({type: 'HEARTBEAT'}));
}
}, 30000);
5.3 应用场景
- 实时监控系统:设备状态、温度、压力等实时数据推送
- 在线协作:多用户实时协同操作
- 即时通讯:聊天消息、通知推送
- 金融交易:实时行情、交易结果通知
- 物联网:设备数据采集与指令下发
6. 总结
本系统提供了一个完整、高效的WebSocket实时消息推送解决方案。通过Netty框架实现了高性能的消息传输,结合Spring事务管理确保了数据一致性,模块化的设计使得系统易于维护和扩展。该系统采用默认配置即可稳定运行,同时提供了良好的扩展接口,适用于各种需要实时数据推送的业务场景,为企业级应用提供了可靠的实时通信能力。
核心价值:
- 开箱即用:无需复杂配置,集成后即可使用
- 零学习成本:业务代码通过简单的API调用即可实现实时推送
- 稳定性保障:事务感知机制确保数据一致性
- 性能优异:基于Netty的架构支持高并发连接