服务器推送消息到前端实现页面数据实时刷新-分布式Vue+Websocket
背景
项目上有个新的需求,需要在系统数据发生改变时,前端页面要实时刷新页面数据。
简单的方案一:
最简单的方式就是直接在前端页面使用定时器定时刷新数据。
这个方案除非是定时的时间设置很短,否则还是会存在页面刷新不及时的情况。但是如果定时时间设置得过短,一旦客户端使用量变多,整个系统的请求数量会变的非常多,需要消耗许多服务器资源。故放弃这个方案。
方案二:
服务端推送的方式,通过使用Websocket,进入页面时,前端就与服务端建立起socket通道,当系统数据发生改变时,在服务端选中需要刷新的页面的socket会话,主动发送消息到前端,通知前端重新请求数据。
这个方案能达到实时刷新的需求,但考虑到的是客户端数量增长上来,建立的socket太多,会不会对占用太多的服务器资源。然后经过自己开发环境的简单测试,建立几千个socket对服务器资源消耗不大,就暂时决定用这个方案了。最终效果如何还是要 看生产环境的表现的。
实现
前端
前端使用的是vue框架
在methods中添加websocket相关函数
data(){
return {
ws:null
}
},
methods: {
websocket() {
//建立socket通道
//process.env.VUE_APP_URL为服务端地址
//code为自定义的参数,主要是用于服务端标识当前会话是哪个用户
this.ws = new WebSocket(
'ws:' +
process.env.VUE_APP_URL +
'/websocket?identity=identity'
);
//socket连接成功后的回调函数
this.ws.onopen = () => {
console.log('websocket连接成功!');
//若项目中没有使用nginx转发请求则忽略这步
//设置定时器,每过55秒传一次数据
//以防长时间不通信被nginx自动关闭会话
//也可以通过修改nginx配置文件延长关闭时间
setInterval(() => {
this.keepAlive(ws);
}, 55000);
};
//接收来自服务端消息的回调函数
//fluseData() 为自定义的数据刷新函数
this.ws.onmessage = evt => {
console.log('已接收来自后台的消息:', evt);
// 刷新数据
this.fluseData();
};
//关闭socket的回调函数
this.ws.onclose = function() {
// 关闭 websocket
console.log('连接已关闭...');
};
// 路由跳转时结束websocket链接
this.$router.afterEach(function() {
this.ws.close();
});
},
//持续向后台发送消息,用于维护socket通道不被nginx关闭
keepAlive(webSocket) {
if (webSocket) {
if (webSocket.readyState == webSocket.OPEN) {
webSocket.send('');
}
}
}
}
在页面加载时调用函数建立socket连接
mounted() {
this.websocket();
}
在页面关闭或销毁时关闭socket
beforeDestroy() {
this.ws.close();
},
后端
引入jar包
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.38</version>
</dependency>
设置websocket配置类
@Configuration
public class MyWebsocketConfig implements ServerApplicationConfig {
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> set) {
return null;
}
@Override
public Set&