《拿下奇怪的前端报错》:1比特丢失导致的音视频播放时长无限增长-浅析http分片传输核心和一个坑点

问题背景

在一个使用MongoDB GridFS实现文件存储和分片读取的项目中,同事遇到了一个令人困惑的问题:音频文件总是丢失最后几秒,视频文件也出现类似情况。更奇怪的是,播放器显示的总时长为无限大。这个问题困扰了团队成员几天,都没有解决,因为架构这块我负责的,最后当然就需要我来深入调查了(本来是想蒙混过去的,毕竟影响其实不大,但因为刚好有点空闲)。

  • 在应用中,音频时长为无限,可以不停的快进也就是时长无限增长,大部分手机都如此,除了一部分手机正常
  • 在浏览器中单独打开音频文件,播放正常
  • 文件使用Mongodb的GridFS存储在数据库,通过http接口对外提供读取接口

HTTP分片传输简介

在深入问题之前,让我们先了解一下HTTP分片传输的基本概念,这对理解后续的调试过程至关重要。这部分内容很久之前看网络相关文档的时候,有初略的了解,大概就是前端请求时,后端支持分片可返回部分数据+总数据长度,然后前端就可以按需读取了。

HTTP分片传输(HTTP Range Requests)允许客户端请求资源的部分内容,而不是整个资源。这在处理大文件,特别是音频和视频流时非常有用。主要涉及以下HTTP头:

  1. Range:客户端在请求中使用此头来指定所需的字节范围。
    例如:Range: bytes=500-999表示请求从第500字节到第999字节的内容。

  2. Content-Range:服务器在响应中使用此头来指明实际返回的字节范围。
    例如:Content-Range: bytes 500-999/1234表示返回的是500-999字节,总文件大小为1234字节。

  3. Accept-Ranges:服务器使用此头来告诉客户端它支持范围请求。

重要的是,HTTP规范中定义的Range是包含性的(inclusive),这意味着Range: bytes=0-499实际上请求了500个字节。这里是一个非常容易出错的点,因为在大多数的编程语言中,对类似数组数据的操作,结尾位置的数据都是不包含的,这也是一个坑点,刚入行不久的小伙伴很可能就跳进去了,毕竟随能够记得那么细呢?而且是一个反常见模式的知识点!

调试过程

1. 初步分析

首先,我注意到播放器的duration显示为无穷大。为了进一步测试,我尝试将currentTime设置为一个非常大的值,但问题依然存在。但是在单独的页面播放和oppo的某手机播放没问题,就猜测是某个特殊点的兼容性问题,但部分尝试做了兼容,所以正常,但大部分的设备或者webview都没有兼容,导致这个问题没被处理,从而出现时长无限。这时候测试得到一个比较重要的信息:

  • 特别小的文件,时长在5秒内的不会出现无限时长,视频文件大概率都会出现

于是就进一步猜测,肯定和网络传输有关,而且和文件体积有关系,这时候想起了大文件分片,因为上传的时候就是分片上传的

2. 网络请求分析

观察到网络请求一直处于pending状态,我怀疑可能是由于socket没有正确关闭导致无限加载。我尝试在数据流关闭后结束请求,但这并没有解决问题。

  1. 而且发现浏览器在不同的发送包内容基本一样的请求

3. 请求头分析

仔细查看请求头,我发现了一些奇怪的Range请求,如Range=11333-11333/11334。起初,我认为可能是因为起始值和结束值相同导致的问题。我尝试在这种情况下重写Range,对于Range=11333-这样的请求则返回416状态码。但这些措施都没有解决问题。

也就是这里引起了我的警觉,因为是不停的在请求,一开始的时候,还以为是触发了某个浏览器的bug,但是分析请求头,有一点引起可我的注意,就是11333-11333/11334 ,为什么会请求这样的数据,第一反应是一个0字节的请求

然后我就开始读HTTP1.1-rfc2616规范文档,发现这了这个反直觉的坑,那就是范围的结尾值是包含的。

这里基本上我猜测到了问题出现的原因,下一步就是验证了

附rfc的说明 - inclusive,开始还不确定这个单词的意思
在这里插入图片描述

4. 深入源码

分析第三方库的源码后,我发现了问题的根源:

  • HTTP的Content-Range头中,start和end都是包含的(inclusive)。
  • 而在JavaScript和MongoDB中,类似slice()这样的操作,end是不包含的(exclusive)。

这种不一致性导致了在处理最后一个字节时出现问题。具体来说:

  1. 当客户端请求最后一个字节时(例如Range: bytes=11333-11333),服务器正确地解释了这个请求。
  2. 但是,当服务器使用JavaScript或MongoDB的API来获取这个范围的数据时,由于end是exclusive的,实际上没有返回任何数据。
  3. 这导致客户端认为还有更多数据需要获取,因此会继续发送请求,造成无限加载的情况。

解决方案

为了解决这个问题,便对getDownloadStream方法进行了修改-重写,类似于下面的方式-先缓存老方法,再修改请求参数,再调用老方法:

const oldFun = obj.a;
obj.a = function(a1, a2) {if (a2.end) {a2.end += 1;}return oldFun(a1, a2);
}

这个简单的修改确保了JavaScript/MongoDB的操作范围与HTTP请求的Range一致,解决了缺少最后一个字节的问题。通过将end值增加1,确保了包含了请求范围的最后一个字节。

经验总结

  1. HTTP协议的深入理解很重要:尤其是请求头参数的精确含义,对于解决复杂问题至关重要。在这个案例中,理解Range请求的包含性本质是解决问题的关键。

  2. 框架设计的重要性:这次调试过程让我意识到了Koa等框架设计的优势。能够在一个中间件中同时处理请求和响应,大大方便了调试过程。

  3. 细节决定成败:在这个案例中,仅仅一个字节的差异就导致了严重的用户体验问题。这提醒我们在处理底层数据时必须格外小心,特别是在处理不同系统间的数据交换时。

  4. 开源贡献的价值:通过这次经历,我不仅解决了自己的问题,还有机会通过PR为开源社区做出贡献,提升了项目的整体质量。这展示了开源社区如何通过集体智慧来解决复杂问题。

  5. 跨系统集成的挑战:这个问题突出了在集成不同系统(如HTTP服务器、JavaScript运行时和MongoDB)时可能遇到的细微差异。在设计跨系统解决方案时,需要特别注意这些潜在的不一致性。

结语

这个看似简单的问题背后隐藏着HTTP协议、JavaScript特性和数据库操作之间的微妙差异。通过耐心的调试和深入的分析,我不仅解决了问题,还加深了对各种技术细节的理解。这再次证明,在软件开发中,“魔鬼藏在细节里”。

对于其他可能遇到类似问题的开发者,建议深入理解所使用的每个组件的特性,特别是在处理底层数据传输时。同时,这个案例也强调了全面测试的重要性,尤其是在处理边界情况时。通过分享这种经验,可以共同提高整个开发社区的技术水平和问题解决能力。

本文主要是复盘之前工作中遇到的一个奇怪的前端问题,并且是我个人的第一次开源代码贡献,还提交了两次,第一次因为格式不对没写注释-个人仓库管理员没接受,第二次说明了情况并详细说明和备注了解释等才通过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/450522.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wps安装教程

WPS office完整版是一款由金山推出的免费办公软件,软件小巧安装快,占用内存极小,启动速度快。WPS office完整版包含WPS文字、WPS表格、WPS演示三大功能模块,让我们轻松办公。WPS的功能是依据OFFICE用户的使用习惯而设计&#xff0…

Java5.--继承-重写-多态

笔记暂未整理: 一、面向对象的第二大特征:继承 1.分类:业务封装 功能封装 2.作用 封装-->属性的安全! 继承-->重用----重用代码(属性方法) 多态-->扩展 3.实现继承的步骤 ①从多个相似的类中…

OpenShift 4 - 云原生备份容灾 - Velero 和 OADP 基础篇

《OpenShift 4.x HOL教程汇总》 说明: 本文主要说明能够云原生备份容灾的开源项目 Velero 及其红帽扩展项目 OADP 的概念和架构篇。操作篇见《OpenShift 4 - 使用 OADP 对容器应用进行备份和恢复(附视频) 》 Velero 和 OADP 包含的功能和模…

精品!“缠论分笔预测”,缠论分笔波段空间预测指标!

精品!“缠论分笔预测”,缠论分笔波段空间预测指标! 使用技巧该指标属于缠论相关指标,可结合缠论使用。使用缠论分笔方法来确定波段的高低点,相比使用“ZIG”算法,似乎更为准确。它能有效减少某些股票高点和…

大模型生图安全疫苗注入赛题解析(DataWhale组队学习)

引言 大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月实践赛的大模型生图安全疫苗注入赛道;本文主要整理本次赛事的基本流程和优化方法。💕💕😊 一…

Unity 山水树木

本章节内容 1. Unity对3D游戏物体的简单操作; 2. 构建山水树木的场景 1. Unity 简易操作 1.1 新建3D游戏场景 1. 打开Unity Hub,点击 New Project (新建项目)按键,选择第二项 3D(Built-In Render Pipeline)&#xf…

harmonyOS next之实现时间打卡定时器

需求:实现一个时间打卡签到按钮。 实现方法:每隔一秒钟获取一下当前时间。 实现代码如下: Column(){Text(this.curTime).fontColor(#FFFFFF).fontWeight(600).fontSize(32vp)Text(上班打卡).fontColor(#FFFFFF) } .width(170vp) .height(170…

【 香格里拉酒店-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞 …

[0633].第3-3节:@SentinueResource注解

我的后端学习大纲 SpringCloud学习大纲 是什么: SentinueResource是一个流量防卫防护组件注解 用于指定防护资源,,对配置的资源进行流量控制、熔断降级等功能 SentinueResource注解说明: Target({ElementType.METHOD, ElementTy…

选择合适的SSL证书

随着我们在线业务的增长,确保网站安全变得越来越重要。对于许多人来说,保护网站安全的想法似乎令人望而生畏,尤其是在有各种SSL证书可用的情况下。您可能想知道哪一个最适合您的业务需求或如何浏览这些选项。 除了SSL证书之外,使…

SQL Injection | SQL 注入 —— 时间盲注

关注这个漏洞的其他相关笔记:SQL 注入漏洞 - 学习手册-CSDN博客 0x01:时间盲注 —— 理论篇 时间盲注(Time-Based Blind SQL Injection)是一种常见的 SQL 注入技术,适用于那些页面不会返回错误信息,只会回…

appium启动hbuild打包的apk异常解决

目录 一、错误信息 二、问题解决 2.1 通过以下命令获取安装包名称: 2.2 这个launcher状态下的安装包名称和active,替换原先的安装包名称 一、错误信息 通过adb shell dumpsys activity | findstr "mResume" 命令获取的安装包信息&#xff…

第十四届单片机嵌入式蓝桥杯

一、CubeMx配置 (1)LED配置 (1)LED灯里面用到了SN74HC573ADWR锁存器,这个锁存器有一个LE引脚,这个是我们芯片的锁存引脚(使能引脚),由PD2这个端口来控制的 (2&#xff…

【前端】如何制作自己的网站(7)

以下内容接上文。 结合图片的超链接 将img元素作为内容,放在a元素中。即可为图片添加一个超链接。 例如右边的代码,点击头像就会打开“aboutme.html“。 点击右边的图片试试~ 两个非文本元素——图片与超链接。 从现在开始&#xff0…

API项目3:API签名认证

问题引入 我们为开发者提供了接口,却对调用者一无所知 假设我们的服务器只能允许 100 个人同时调用接口。如果有攻击者疯狂地请求这个接口,那是很危险的。一方面这可能会损害安全性,另一方面耗尽服务器性能,影响正常用户的使用。…

Golang | Leetcode Golang题解之第492题构造矩形

题目: 题解: func constructRectangle(area int) []int {w : int(math.Sqrt(float64(area)))for area%w > 0 {w--}return []int{area / w, w} }

DeBiFormer:带有可变形代理双层路由注意力的视觉Transformer

https://arxiv.org/pdf/2410.08582v1 摘要 带有各种注意力模块的视觉Transformer在视觉任务上已表现出卓越的性能。虽然使用稀疏自适应注意力(如在DAT中)在图像分类任务中取得了显著成果,但在对语义分割任务进行微调时,由可变形…

【论文精读】RELIEF: Reinforcement Learning Empowered Graph Feature Prompt Tuning

RELIEF: Reinforcement Learning Empowered Graph Feature Prompt Tuning 前言AbstractMotivationSolutionRELIEFIncorporating Feature Prompts as MDPAction SpaceState TransitionReward Function Policy Network ArchitectureDiscrete ActorContinuous ActorCritic Overall…

Firefox火狐浏览器打开B站视频时默认静音

文章目录 环境问题解决办法 环境 Windows 11家庭版Firefox浏览器 131.0.2 (64 位) 问题 用Firefox浏览器打开B站的视频时,默认是静音播放的: 而其它浏览器,比如Chrome和Edge,默认是带声音播放的。 虽然不是什么大问题&#xf…

二叉树与堆讲解

目录 1.树的概念及结构 1.树的概念 2.树的相关概念 3.树的表示 2.二叉树 1.概念 2.特殊的二叉树 1.满二叉树 2.完全二叉树 3.二叉树的性质 4.二叉树的存储结构 1.顺序结构 2.链式存储 3.堆 1.堆的概念及结构 2.堆的实现 1.堆的创建 2.堆的初始化(H…