万万没想到,一个不起眼的小功能,差点把我们项目搞崩溃!

2024-06-12 02:44

本文主要是介绍万万没想到,一个不起眼的小功能,差点把我们项目搞崩溃!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家好,我是程序员鱼皮。今天分享一个真实项目开发的小故事。

故事

最近我们团队一直在持续更新编程导航网站,优化了界面,也新增了不少功能。现在网站长下面这样,是不是看着比以前舒服多了?

编程导航:https://code-nav.cn

当然,项目更新就意味着引入了新的 Bug。万万没想到,前两天我们优化了一个不起眼的小功能,差点把我们的项目搞崩溃了!

就是右上角这个看起来毫不起眼的消息通知小图标,以前我们只在用户刷新进入页面时会查询一次当前用户的未读消息数,后来为了提升用户体验,我们更改了下获取消息的逻辑,改为每隔 10 秒定时查询更新,让用户能够及时获取到最新的消息。

这种操作俗称 “轮询请求”,也是前端实时获取后端数据变化的一种方法。但是有经验的朋友,能不能想到我们这么修改后可能会出现什么问题?

起初我也没在意,结果前几天看我们后端监控的时候,发现了一个反常的现象。

哝,下面这个,是我们系统接口的调用量分布图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我觉得反常的点在于:为什么凌晨两点多,还能有这么多调用量?说实在的,我不相信大半夜这么多人还在偷偷卷。

其实我本能地联想到,应该是获取未读消息的轮询接口,在一直被调用。让团队的同学查日志确认后,果不其然凶手就是它!

原因也很简单,一旦用户打开了网页,哪怕之后去睡觉了,只要网页不关闭,照样会定时发送轮询请求。像我这种习惯开一堆网页又几乎不关电脑的朋友,应该还是挺多的,一个人就有可能 “贡献” 一大堆请求。要不是我对目前的用户量心里有点 btree,还真特么以为用户增长爆了呢!

解决问题

那么如何解决这个问题呢?

1、调整时间间隔

首先最简单的方法,就是延长轮询的时间间隔,比如将 10 秒延长到 20 秒、30 秒等等。

可以参考别家的网站,时间间隔设置长一点完全没有问题。

2、页面活跃状态监控

在用户离开页面时停止轮询请求,用户返回页面时重新开始轮询,这样就不会出现请求浪费的情况。

利用浏览器提供的 visibilitychange 事件就可以实现了,非常简单:

document.addEventListener('visibilitychange', function() {if (document.visibilityState === 'hidden') {console.log('用户离开当前页面');// 用户离开页面时的处理逻辑} else if (document.visibilityState === 'visible') {console.log('用户回到当前页面');// 用户返回页面时的处理逻辑}
});

回归到我们的项目,用户离开页面时移除轮询请求的定时执行器(setInterval),进入页面时再重新启动定时执行器即可。

但是,仅通过这个事件判断用户是否活跃还不够。如果用户不是直接切换浏览器当前窗口的 tab 页,而是新打开了一个窗口,也不会触发上述事件。我们还可以监听窗口失焦事件,判断用户是否切换了窗口。示例代码如下:

function handleWindowBlur() {console.log('用户离开当前窗口');// 用户离开窗口时的处理逻辑
}function handleWindowFocus() {console.log('用户回到当前窗口');// 用户回到窗口时的处理逻辑
}// 添加事件监听器
window.addEventListener('blur', handleWindowBlur);
window.addEventListener('focus', handleWindowFocus);

但是,仅通过这些事件判断用户是否活跃还不够!用户还可以挂在页面内不做任何动作,所以我们还要对一些鼠标、键盘事件进行监听,指定时间内没有触发这些事件,就标记为不活跃。

const ACTIVE_ACTIONS = ['mousemove', // 鼠标移动'mousedown', // 鼠标按下'touchstart', // 触摸屏幕【移动端】'wheel', // 鼠标滚轮'keydown', // 键盘输入
];// 批量添加事件监听
ACTIVE_ACTIONS.map((event) => window.addEventListener(event, onActive));

有些视频网站就是这么干的,用户如果切换窗口,就把视频暂停,不要浪费流量。

对了,有个重要事项,给页面绑定事件后,在页面销毁或切换路由时,记得删除已绑定的事件!

3、精简接口数据

保证轮询接口返回数据的精简非常重要。

很多经验不足的同学容易出现的问题是,在后端直接通过 select 把所有数据和字段查出来返回给前端,一把梭。这其实会产生性能的浪费,比如博客系统的列表页,其实不用返回每篇博客完整的文章内容,有个标题、描述等信息就够了。对于轮询接口,就更要注意这点,比如我们要获取未读消息,不是一次性把所有未读消息列表返回给前端,而是只需要返回未读消息数即可,需要拉取未读消息列表时,再进行获取。可以大大节约带宽占用和流量。

4、其他技术实现

还有其他的方案,就是干脆不用轮询技术,改为使用 SSE 或者 WebSocket 之类的实时通讯技术,前端和服务器建立一个长连接,由服务器定时推送数据给前端,而不是前端主动请求。

随着 AI 的发展,SSE 技术也被带火了,很适合 AI 生成内容的场景,我最新带大家做的 AI 答题应用平台,就用到了 AI + SSE 来自动生成题目。代码开源:https://github.com/liyupi/yudada

但我们并没有选择使用这些技术,反而一定程度上增加了开发成本和系统复杂度,通过前 3 种方案就可以解决问题啦~


可访问我的 Github:https://github.com/liyupi ,了解更多技术和项目内容。

这篇关于万万没想到,一个不起眼的小功能,差点把我们项目搞崩溃!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1052975

相关文章

Spring Boot整合Redis注解实现增删改查功能(Redis注解使用)

《SpringBoot整合Redis注解实现增删改查功能(Redis注解使用)》文章介绍了如何使用SpringBoot整合Redis注解实现增删改查功能,包括配置、实体类、Repository、Se... 目录配置Redis连接定义实体类创建Repository接口增删改查操作示例插入数据查询数据删除数据更

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

idea+spring boot创建项目的搭建全过程

《idea+springboot创建项目的搭建全过程》SpringBoot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目,:本文主要介绍idea+springb... 目录一.idea四种搭建方式1.Javaidea命名规范2JavaWebTomcat的安装一.明确tomcat

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

使用EasyPoi快速导出Word文档功能的实现步骤

《使用EasyPoi快速导出Word文档功能的实现步骤》EasyPoi是一个基于ApachePOI的开源Java工具库,旨在简化Excel和Word文档的操作,本文将详细介绍如何使用EasyPoi快速... 目录一、准备工作1、引入依赖二、准备好一个word模版文件三、编写导出方法的工具类四、在Export

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

MyCat分库分表的项目实践

《MyCat分库分表的项目实践》分库分表解决大数据量和高并发性能瓶颈,MyCat作为中间件支持分片、读写分离与事务处理,本文就来介绍一下MyCat分库分表的实践,感兴趣的可以了解一下... 目录一、为什么要分库分表?二、分库分表的常见方案三、MyCat简介四、MyCat分库分表深度解析1. 架构原理2. 分

C#实现高性能拍照与水印添加功能完整方案

《C#实现高性能拍照与水印添加功能完整方案》在工业检测、质量追溯等应用场景中,经常需要对产品进行拍照并添加相关信息水印,本文将详细介绍如何使用C#实现一个高性能的拍照和水印添加功能,包含完整的代码实现... 目录1. 概述2. 功能架构设计3. 核心代码实现python3.1 主拍照方法3.2 安全HBIT

linux查找java项目日志查找报错信息方式

《linux查找java项目日志查找报错信息方式》日志查找定位步骤:进入项目,用tail-f实时跟踪日志,tail-n1000查看末尾1000行,grep搜索关键词或时间,vim内精准查找并高亮定位,... 目录日志查找定位在当前文件里找到报错消息总结日志查找定位1.cd 进入项目2.正常日志 和错误日