编程 踩坑浏览器节能机制导致Websocket断连的问题!

2024-11-19 05:31:36 +0800 CST views 855

浏览器节能机制导致Websocket断连的巨坑!


你踩过吗?浏览器节能机制导致WebSocket断连的坑~~~

近期,在使用WebSocket(WS)连接时遇到了频繁断连的问题。这种情况在单个用户上每天发生数百次。尽管利用了 socket.io 的自动重连机制能够在断连后迅速恢复连接,但这并不保证每一次重连都能成功接收WS消息。经过一系列排查和测试,最终发现问题的根本原因竟然是——浏览器的节能机制


浏览器节能机制简介

现代浏览器为了减少电能消耗和提高电池续航能力,逐渐引入了节能机制。这些机制包括但不限于:

  • 降低空闲标签页的CPU使用率
  • 减少后台JavaScript的执行频率
  • 限制定时器的精确度

尽管这些措施显著提高了设备的能效,但也给前端开发带来了新的挑战,尤其是在涉及定时任务或WebSocket连接时。


WS频繁断连原因分析

查阅 socket.io 官网文档,发现服务端配置的 pingTimeoutpingInterval 两个参数与WS心跳机制密切相关。

WS连接中心跳机制的关键点:

  • 服务器发送 ping,如果客户端在 pingTimeout 毫秒内没有用 pong 应答,则服务器认为连接已关闭。
  • 客户端如果在 pingInterval + pingTimeout 毫秒内未收到服务器的 ping,则客户端也会认为连接已关闭。

在高版本的 socket.io 中,心跳由服务端定时发起,而在 2.x 版本中,心跳由客户端定时发起。当浏览器在后台运行时,即使设置了每秒触发的定时器,实际触发间隔却被延长至每分钟一次,这远远超过了 pingInterval + pingTimeout 的设置时间,导致WS频繁断连。


WS频繁断连的解决方法

1. 升级 socket.io 到最新版本

升级到 socket.io 4.x 版本,由服务器定时发起心跳,从而避开浏览器节能机制对定时器的影响。

2. 自定义WS心跳事件

为了减少升级带来的影响,可以使用自定义心跳事件,在服务端定时发送 custom-ping 消息。

// 客户端代码
io.on('custom-ping', function () {
  io.emit('custom-pong', Date.now());
});

// 服务端代码
io.on('connection', (socket) => {
  console.log('New client connected');

  // 定时发送自定义ping消息
  const pingInterval = setInterval(() => {
    socket.emit('custom-ping', Date.now());
  }, 10000); // 每10秒发送一次

  // 监听自定义pong消息
  socket.on('custom-pong', (data) => {
    console.log('Pong received:', data);
  });

  socket.on('disconnect', () => {
    clearInterval(pingInterval);
    console.log('Client disconnected');
  });
});

3. 使用 setTimeout 函数的正确姿势

直接使用 setTimeout 仍然可能会丢失精度,正确的使用方式如下:

// 客户端代码
let timer;

const onHeart = () => {
  if (timer) {
    clearTimeout(timer);
  }
  timer = window.setTimeout(() => {
    socket.emit('custom-ping', Date.now());
  }, 5000);
};

socket.on('custom-pong', onHeart);

// 服务端代码
socket.on('custom-ping', () => {
  socket.emit('custom-pong', Date.now());
});

4. 使用 Web-Workers

在 Web-Workers 线程内发起定时任务,不受浏览器节能机制的限制。


小结

WS频繁断连的原因总结:

  1. 使用了低版本(2.x)的 socket.io
  2. 在客户端每5秒定时发送心跳
  3. 浏览器后台运行时触发节能机制,限制定时器的精度,由每5秒变为实际的每分钟执行一次
  4. 每分钟执行一次远超 pingTimeout 设置时间,导致WS断开连接
  5. socket.io 内置的重连机制立即重连成功,但实际日志显示每分钟重连一次

通过上述方法,我们可以有效解决浏览器节能机制对定时器精度降低带来的WebSocket频繁断连问题,从而提升用户体验。


随着浏览器技术的发展,节能机制无疑会越来越完善,但这也给前端开发带来了新的挑战。了解和适应这些变化,采用正确的策略来解决由此引发的问题,对于开发高质量的前端应用至关重要。

复制全文 生成海报 Web开发 网络编程 性能优化 前端技术

推荐文章

Vue3中如何处理权限控制?
2024-11-18 05:36:30 +0800 CST
liunx宝塔php7.3安装mongodb扩展
2024-11-17 11:56:14 +0800 CST
介绍Vue3的静态提升是什么?
2024-11-18 10:25:10 +0800 CST
Python设计模式之工厂模式详解
2024-11-19 09:36:23 +0800 CST
pin.gl是基于WebRTC的屏幕共享工具
2024-11-19 06:38:05 +0800 CST
一些高质量的Mac软件资源网站
2024-11-19 08:16:01 +0800 CST
Vue3中如何处理组件间的动画?
2024-11-17 04:54:49 +0800 CST
Vue3中如何实现插件?
2024-11-18 04:27:04 +0800 CST
设置mysql支持emoji表情
2024-11-17 04:59:45 +0800 CST
MySQL 优化利剑 EXPLAIN
2024-11-19 00:43:21 +0800 CST
如何优化网页的 SEO 架构
2024-11-18 14:32:08 +0800 CST
防止 macOS 生成 .DS_Store 文件
2024-11-19 07:39:27 +0800 CST
开发外贸客户的推荐网站
2024-11-17 04:44:05 +0800 CST
如何实现虚拟滚动
2024-11-18 20:50:47 +0800 CST
前端如何一次性渲染十万条数据?
2024-11-19 05:08:27 +0800 CST
Nginx 防止IP伪造,绕过IP限制
2025-01-15 09:44:42 +0800 CST
浏览器自动播放策略
2024-11-19 08:54:41 +0800 CST
Nginx 防盗链配置
2024-11-19 07:52:58 +0800 CST
浅谈CSRF攻击
2024-11-18 09:45:14 +0800 CST
Rust 与 sqlx:数据库迁移实战指南
2024-11-19 02:38:49 +0800 CST
维护网站维护费一年多少钱?
2024-11-19 08:05:52 +0800 CST
mysql 优化指南
2024-11-18 21:01:24 +0800 CST
程序员茄子在线接单