blog tumbnail

WebSocket 长时间未操作断开连接

WebSocket 长时间未操作断开连接

问题

最近公司实现一个告警推送的功能,前端将设备 ID 传给后端,后端将实时告警数据源源不断的传送给前端。本来功能一切正常,可是当数据量一大,WebSocket 就会自动断开连接。

原因

通过网上检索发现,造成该问题的原因是当数据量大时,后端获取返回数据的时间会变久,而 nginx 转发 WebSocket 连接时,后端超一分钟未返回数据,会自动断开该链接。如果用户量不大,可以设置 proxy_read_timeout 来延长等待时间。不过这不符合我这边的需求。因为我这边是监控屏,可能很长时间都不会有人操作。这样不管设置多长时间,都没有用处。在查阅资料后,发现可以使用心跳机制。

解决方案

心跳机制是每隔一段时间就向服务器发送一个数据包,检查与服务器的连接是否还正常,顺带告诉服务器,继续保持连接。如果没收到服务器的回传数据,那就是连接断开了,需要进行重新连接。

export default { name: "App", data() { return { ws: null, // ws 连接 heartTimer: null // 定时器 }; }, created() { this.socketInit(); }, methods: { socketInit() { if (typeof WebSocket === "undefined") { alert("您的浏览器不支持WebSocket,将无法展示数据"); } else { const wsUrl = `xxxx`; this.ws = new WebSocket(wsUrl); this.ws.onopen = this.socketOpen; this.ws.onmessage = this.socketMessage; this.ws.onerror = this.socketError; } }, socketOpen(res) { // 监听链接成功回调 const message = "I am alive"; this.socketSendMessage(message); }, socketError(err) { if (this.ws && this.ws.onopen) { this.socketOpen(); } else { this.socketInit(); } }, socketClose(res) { this.socketInit(); }, socketSendMessage(msg) { this.ws.send(JSON.stringify(msg)); }, socketMessage(msg) { // 重置定时器 this.sendHeart() /* 处理业务逻辑 */ }, sendHeart() { // 每 50 s 发送一次 clearInterval(this.heartTimer); this.heartTimer = setInterval(() => { this.socketOpen(); }, 50000); } }, };