基于WebSocket的实时消息传递设计
概述
web管理系统中可以对业务数据执行新增和删除,现在需要当业务数据发生新增或删除操作后,尽可能实时的反应到WPF客户端上面。
web管理系统用VUE编写,后端服务为SpringBoot,WPF客户端基于.Netframework4.8编写。
整体架构
title: 交互时序图
web前台->>+web后端服务:新增数据
Note over web前台,web后端服务:caremaId,labelInfo,......
web后端服务->>+WebSocketServer:创建websocker消息
Note over web后端服务,WebSocketServer:Must:cameraId=clientId
WPF客户端1-->>+WebSocketServer:创建监听
Note over WPF客户端1,WebSocketServer:clientId
WPF客户端2-->>+WebSocketServer:创建监听
Note over WPF客户端2,WebSocketServer:clientId
WebSocketServer->>WPF客户端1:分发websocker消息
Note over WebSocketServer,WPF客户端1:依据:cameraId=clientId
WebSocketServer->>WPF客户端2:分发websocker消息
Note over WebSocketServer,WPF客户端2:依据:cameraId=clientId
设计
流程设计
- 用户在浏览器界面执行新增业务数据操作,调用后端新增接口
- WPF客户端在启动的时候初始化websocket客户端,并创建对server的监听
- 后端新增接口先将数据落库,而后调用websocket服务端产生消息,消息在产生后立马被发送到了正在监听中的websocket-client
- websocket-server和websocket-client是一对多的关系,如何保证业务数据被正确的分发?监听的时候给server端传递一个全局唯一的clientId,业务数据在产生的时候关联到一个BizId上面,只要保证clientId=BizId就可以了。
- 删除流程和新增类似
程序设计
WebSocketServer
概述
WebSocketServer端采用SpringBoot双色球129期开奖结果
实现,通过在springboot-web项目中集成 org.springframework.boot:spring-boot-starter-websocket
实现websocket的能力。
新增pom
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
新增配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
创建websocket端点
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/ws/label/{clientId}")
@Component
public class LabelWebSocket {
/**
* session list
*/
private static ConcurrentHashMap<String, Session> sessionList = new ConcurrentHashMap<>();
/**
* 当前 clientId
*/
private String currentClientId = "";
@OnOpen
public void open(Session session, @PathParam("clientId") String clientId) throws IOException {
if (sessionList.containsKey(clientId)) {
sessionList.remove(clientId);
}
sessionList.put(clientId, session);
currentClientId = clientId;
this.sendMsg(session, "connectok");
}
@OnClose
public void close(Session session) throws IOException {
sessionList.remove(currentClientId);
System.out.println("连接关闭,session=" + JSON.toJSONString(session.getId()));
}
@OnMessage
public void receiveMsg(Session session, String msg) throws IOException {
this.sendMsg(session, "接收到的消息为:" + msg);
// throw new RuntimeException("主动抛异常");
}
@OnError
public void error(Session session, Throwable e) throws IOException {
System.out.println("连接异常,session=" + JSON.toJSONString(session.getId()) + ";currentClientId=" + currentClientId);
this.sendMsg(session, "发生异常,e=" + e.getMessage());
e.printStackTrace();
}
/**
* @param clientId
* @param msg
*/
public boolean sendMsg(String clientId, String msg) throws IOException {
if (sessionList.containsKey(clientId)) {
Session session = sessionList.get(clientId);
this.sendMsg(session, msg);
return true;
} else {
return false;
}
}
private void sendMsg(Session session, String msg) throws IOException {
session.getBasicRemote().sendText(msg);
}
}
WebSocketClient
概述
WebSocketClient端集成在WPF应用客户端中,通过前期调研,选中 WebSocketSharp 作为websocketclient工具,WebSocketSharp 是托管在Github的开源项目,MITLicense,目前4.9K的star。
安装WebSocketSharp
//nuget
Install-Package WebSocketSharp -Pre
初始化client
WebSocket ws = new WebSocket("ws://127.0.0.1:8083/ws/xx/clientId");
创建连接
private void InitWebSocket()
{
ws.OnOpen += (sender, e) =>
{
Console.WriteLine("onOpen");
};
//允许ping
ws.EmitOnPing = true;
//接收到xiaoxi
ws.OnMessage += (sender, e) =>
{
ReceiveMessage(sender, e);
};
ws.Connect();
//发送消息
//ws.Send("BALUS")
;
}
private void ReceiveMessage(object sender, MessageEventArgs e)
{
if (e.IsText)
{
// Do something with e.Data.like jsonstring
Console.WriteLine(e.Data);
return;
}
if (e.IsBinary)
{
// Do something with e.RawData. like byte[]
return;
}
if (e.IsPing)
{
// Do something to notify that a ping has been received.
return;
}
}
接口设计
新增接口
概述
目前WebSocketServer和web后端服务是在同一个SpringBoot的工程中,所以只要将WebSocketServer托管到SpringContainer中,web后端服务可以通过 DI 的方式直接访问 WebSocketEndPoint。
如果考虑程序的低耦合,可以在WebSocketServer和web后端服务之间架设一个MQ。
核心代码
@Autowired
private LabelWebSocket ws;
@GetMapping("/create")
public boolean createLabel() throws IOException {
String cameraId = "cml";
//todo
boolean result = ws.sendMsg(cameraId, "新增标签");
return result;
}
风险
分布式风险
当前在 WebSocketServer 中,已经连接的client信息是记录在当前双色球 的cache中,如果服务做横向扩容,cache信息无法在多实例双色球 中传递,将导致无法正确的处理业务数据,并可能会发生意想不到的异常和bug,此问题在并发越高的情况下造成的影响越大
资源风险
web后端服务为基于java语言的springboot程序,这种类型程序的特点是内存消耗特别严重。WebSocketServer服务在本项目中仅用作消息中间件,连通web后端服务和WPF客户端。
首先WebSocketServer没有太多的计算能力的消耗,内存消耗会随着连接客户端数量的增长而增长,网络将是最大的开销,一方面需要转发来自web后端服务的业务数据,并和WPF客户端保持长连接;另一方面WebSocketServer和WPF客户端的交互可能会走公网,而其和web后端服务必然是在局域网环境。
综上,将web后端服务和WebSocketServer分开部署对于硬件资源成本和利用率来说是最好的选择。
高可用风险
未引入重试机制,当某一个环节失败之后,将导致异常情况发生。
基于WebSocket的实时消息传递设计的更多相关文章
- Socket.IO – 基于 WebSocket 构建跨浏览器的实时应用
Socket.IO 是一个功能非常强大的双色球129期开奖结果 ,能够帮助你构建基于 WebSocket 的跨浏览器的实时应用.支持主流浏览器,多种平台,多种传输模式,还可以集合 Exppress 双色球129期开奖结果 构建各种功能复杂 ...
- 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(二)
我们上一篇<基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)>主要讲解了如何搭建一个实时数据通讯服务器,客户端与服务端是如何通讯的,相信通过上一篇的讲解,再配 ...
- 基于MATLAB的GUI(Graphical User Interface)音频实时显示设计
摘要:本文章的设计主要讲基于matlab的gui音频实时显示设计,此次设计的gui相当于一个简洁的音乐播放器,界面只有”录音“和”播放“两个控件,哈哈,够简洁吧.通过”录音“按钮可以实现声音从电脑的声 ...
- 基于 WebSocket 构建跨浏览器的实时应用
Socket.IO – 基于 WebSocket 构建跨浏览器的实时应用 Socket.IO 是一个功能非常强大的双色球129期开奖结果 ,能够帮助你构建基于 WebSocket 的跨浏览器的实时应用.支持主流浏览器,多 ...
- 基于 WebSocket 的 MQTT 移动推送方案
WebSphere MQ Telemetry Transport 简介 WebSphere MQ Telemetry Transport (MQTT) 是一项异步消息传输协议,是 IBM 在分析了他们 ...
- 网络编程-基于Websocket聊天室(IM)系统
目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...
- Go实现基于WebSocket的弹幕服务
拉模式和推模式 拉模式 1.数据更新频率低,则大多数请求是无效的 2.在线用户量多,则服务端的查询负载高 3.定时轮询拉取,实时性低 推模式 1.仅在数据更新时才需要推送 2.需要维护大量的在线长连接 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- [转]使用 HTML5 WebSocket 构建实时 Web 应用
HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例 ...
- 使用 HTML5 WebSocket 构建实时 Web 应用
原文地址://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ HTML5 WebSocket 简介和实战演练 本文主要介绍 ...
随机推荐
- 齐博x1内容评论标签的风格制作
评论的标签如下: {qb:comment name="xxxxx" rows='5'} HTML代码片段 {/qb:comment} 评论涉及到的元素有{posturl} 这个是代 ...
- golang中的一些实用功能
0.1.索引 //waterflow.link/articles/1663921524839 通过使用一些通用代码来节省时间,而无需单独实现它们.以下是一些开发中经常会用到的函数实现的列表 ...
- Tensorflow Lite从入门到精通
TensorFlow Lite 是 TensorFlow 在移动和 IoT 等边缘设备端的解决方案,提供了 Java.Python 和 C++ API 库,可以运行在 Android.iOS 和 Ra ...
- Android开发 对接微信分享SDK总结
原文:Android开发 对接微信分享SDK总结 - Stars-One的杂货小窝 公司项目需要对接微信分享,本来之前准备对接友盟分享的,但友盟的分享实际参数太多,而我又只需要对接一个微信分享,于是便 ...
- Codeforces Global Round 18 B. And It's Non-Zero(按位前缀和)
题目大意:求一段数(l到r)的按位与结果不为零需要删除中间元素的最小个数 思路:按位与使得结果不为0只要有某一位全是1即可,所以只要统计每一位1的个数,用总个数减去1的个数就是某一位0的个数 删除包含 ...
- C# 获取打开的EXCEL中某列的行数
背景 在通过C#操作EXCEL时 获取行数 int iRowCount = worksheet.get_Range("A65535", oMissing).get_End(MExc ...
- Seata Server 1.5.2 源码学习
Seata 包括 Server端和Client端.Seata中有三种角色:TC.TM.RM,其中,Server端就是TC,TM和RM属Client端.Client端的源码学习上一篇已讲过,详见 < ...
- 匿名方法、Lambda表达和自定义泛型委托以及Func、Action系统泛型委托
1.匿名方法的概念:一个方法没有具体的名称,而只有关键字delegate.方法参数.方法体.这种方法是匿名方法. 匿名方法的好处:将具体方法和委托直接关联在一起,如果我们基于委托只需要一个方法的时候, ...
- Java标准类
一个标准的类通常要拥有以下四个组成部分 1.所有的成员变量都要使用private关键字修饰 2.为每一个成员变量编写一对儿Getter/Setter方法 3.编写一个无参数的构造方法 4.编写一个全参 ...
- requests模块/openpyxl模块/简单爬虫实战
内容概要 第三方模块的下载及使用 网络爬虫及requests模块 网络爬虫实战爬取二手房信息 自动化办公领域模块openpyxl 练习题及答案 第三方模块的下载 第三方模块就类似与别人写好的模块,我们 ...