佬们,我现在想要做一个硬件监控系统,前端是微信小程序。首先使用mqtt协议将硬件与java后端通信,这步实现了。因为监控系统嘛,后端一收到硬件信息就主动推送给前端该设备的所有者。想到使用websocket实现后端主动推送信息,但是会有很多用户同时在小程序查看设备,没办法建立这么多websocket连接怎么办呢
以微信小程序作为客户端,建立与服务端简的WebSocket连接,客户端操作详情请参考微信小程序MQTT通信及开源框架实现,本文关注基于WebSocket进行MQTT的流程。
建立WebSocket连接由两个步骤完成:
其代码实现如下:
/**
* 唯一的一次http请求,用于创建websocket
*/
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
// 要求Upgrade为websocket,过滤掉get/Post
if (!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
// 若不是websocket方式,则创建BAD_REQUEST的req,返回给客户端
sendHttpResponse(ctx, req,
new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
return;
}
logger.info(req.content());
// ctx.fireChannelRead(req.content());
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
"ws://localhost:1885/websocket",
"mqtt", false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
} else {
req.headers().set("Sec-WebSocket-Protocol", "mqtt");
handshaker.handshake(ctx.channel(), req);
}
}
识别出收到的报文是Http报文时在第22行进行握手完成协议升级成websocket协议建立连接。
建立连接过程跟踪
采用wireshark工具对连接过程进行跟踪可以看到如下报文信息:
WebSocket连接建立报文跟踪
从服务器端返回的101报文表示建立连接成功。
可以考虑使用WebSocket的广播机制来优化这个问题,避免建立多个WebSocket连接。具体实现方法如下:
1.在后端建立一个WebSocket连接,并且保存下来。 2.使用一个数据结构来保存所有需要推送的消息,这个数据结构可以使用队列、堆栈等等,根据实际需求选择。 3.当有需要推送的消息时,将消息加入数据结构中。 4.使用WebSocket的广播机制,将数据结构中的消息发送给所有客户端; 5.客户端收到消息后,将其展示在界面上。
具体的实现细节可以参考以下代码示例:
后端代码示例:
// 建立WebSocket连接 private void initWebSocket() { // 创建一个WebSocketServerHandshakerFactory对象 WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( "ws://localhost:8888/websocket", null, false);
// 通过WebSocketServerHandshakerFactory对象创建一个WebSocketServerHandshaker对象
handshaker = wsFactory.newHandshaker(request);
if (handshaker == null) {
WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
} else {
// 向客户端发送握手消息
ChannelFuture future = handshaker.handshake(ctx.channel(), request);
if (future.isSuccess()) {
// WebSocket连接建立成功
// 将当前连接保存到ChannelGroup中
channelGroup.add(ctx.channel());
}
}
}
// 推送消息给所有客户端 private void sendMessageToAllClients(Message message) { // 将消息加入消息队列中 messageQueue.offer(message);
// 广播消息给所有客户端
for (Channel ch : channelGroup) {
if (ch.isActive()) {
ch.writeAndFlush(new TextWebSocketFrame("push:" + message.getContent()));
}
}
}
// 接收客户端发送的消息 @Override protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { if ("heartbeat".equals(msg.text())) { // 心跳消息,不做处理 return; }
// 将客户端发送的消息转换成Message对象,并且推送给所有客户端
Message message = convertToMessage(msg.text());
sendMessageToAllClients(message);
}
前端代码示例:
// 建立WebSocket连接 var ws = new WebSocket("ws://localhost:8888/websocket");
// 监听WebSocket连接 ws.onopen = function() { console.log("WebSocket连接已建立"); };
// 监听WebSocket消息 ws.onmessage = function(event) { console.log("接收到消息:" + event.data); };
// 向服务器发送消息 ws.send("hello");
以上代码示例仅供参考,具体实现细节需要根据实际需求进行相应的修改和调整。
你的思路是没有问题的,可以使用websocket 作为消息通知组件。你说的用户太多没办法建立太多websocket连接。按道理websocket的底层协议TCP 是没有连接数限制的,所以不用担心这个。通常WebSocket可以支持成千上万的连接。
你先把服务搞出来,做个简单的压测,看下具体承载量。如果达不到预期,要么堆硬件使用多个WebSocket服务器进行负载均衡。要么可以通过调整服务器的线程池大小、网络缓冲区大小、连接超时时间等参数,来优化服务器的性能和连接数。不要一上来担心技术上的问题,你需要做的是把你的程序优化好,至少在你的应用层保证心跳检测、断线重连、连接池等功能的实现。有那么大的用户量,就应该有那么大的基础设施的投入。