当前位置: 首页 > news >正文

下载视频大量丢帧:UDP → TCP

我们最开始使用 UDP 进行下载。发现下载视频中间有大量丢帧,影响用户使用。
首先排查网络。tcpdump 分段抓包,统计 RTP 序列号的连续性,确实能观测到批量丢包,严重时丢包率不低。
由此分析出大量丢帧是由于UDP丢包导致,可以换成TCP通信, 解决丢包的问题。
切换成 TCP 之后,UDP 丢包问题解决了。有遇到信息问题:下载经常断开,概率很高。
又回到网络排查的思路上:

参数试错:关闭 ZLMediaKit 的 paced_sender_ms 平滑发送、把 HTTP keepalive 从 30 秒延长到 180 秒,断连概率轻微下降但远未根治;
抓包排除:反复抓包、逐节点排查网络层,确认不是防火墙、交换机、链路抖动的问题。
两步排查走完,开始怀疑不是网络层的问题。

三、问题一:中途断连
分析
接下来在流媒体推流模块加日志后,断开前的 pattern 很清晰:发送缓冲区持续增长 → write() 返回异常 → 应用层主动 close()。
由于上级平台接收速度慢,导致数据不能及时发送出去,TCP 滑动窗口逐渐缩小,下级内核发送缓冲区最终堆满,应用层捕获异常后主动断开连接。

修复
流媒体服务器做如下改动:推流时判断前次数据是否已发送完成。每次推流前检查上次发送是否完成,如果未完成,则等待一段时间,不往 socket 里塞新数据。以本地发送完成状态做自我节流。不需要探测对端,不需要改协议。
修复后,中途断连问题解决。

四、问题二:提前结束
现象
断连修完之后,过一段时间,又暴露出来一个问题:下载完成后,文件的时长偶尔小于期望,极端情况下1小时能小3分钟以上。严重影响用户使用。

分析
排查 GB28181 的下载完成机制后发现:下级平台流媒体推送完成后,立即触发完成回调给国标信令平台,信令平台发送 SIP MESSAGE(121)通知给上级,结束下载。但 SIP 信令和 RTP 媒体走两套独立通道——下级发完最后一帧就发 121,信令先发到上级平台,结束下载,文件截断。

修复
第一步:流媒体服务器在推流完成后,不立即触发完成回调,而是等发送缓冲区真正清空——确认数据已经从 socket 发出去了——再触发回调。

第二步:上级平台侧在收到 SIP 121 通知后,延迟一段时间再结束下载,让在途数据有最后到达的机会。

改造前后的时序差异:

上级平台
网络
下级平台
上级平台
网络
下级平台
改造前:信令跑赢媒体帧,录像截断
滞后RTP帧直接丢弃
改造后:缓冲区排空再发信令,延时兜底
等待socket内核缓冲区完全排空
延时窗口等待在途数据
推送最后一批RTP媒体帧
立即下发SIP 121结束通知
收到通知,关闭文件写入
推送最后一批RTP媒体帧
下发SIP 121结束通知
全部媒体帧接收完成
正常关闭,生成完整录像
修复之外,还做了几项配套调整:ZLMediaKit 的 paced_sender_ms 平滑发送参数优化、HTTP keepalive 超时延长,辅助缓解高倍速下缓冲区压力;倍速拉流时根据上游实际接收吞吐动态限制推送速率,避免下游无脑满速推送;对齐上下游 RTP SSRC 标识,消除流匹配的隐性异常。这些不是主修复,但少了它们,极端场景下仍然可能触发边界问题。

落地效果
UDP 丢包:切换 TCP 后彻底解决
TCP 中途断连:发送端节流机制上线后未再复现
录像截断:双层时序防护上线后,取证录像100% 完整,不再出现时长缺失
性能:整套逻辑改造为应用层纯逻辑,无额外 CPU、内存开销,平台并发承载能力不受影响
五、回头看
整条链路走下来,四个阶段:UDP 丢包 → 切 TCP → 中途断连 → 提前结束。后面两个问题排查成本远高于修复成本,各自只有几行代码的改动量。

几条踩过的坑,后来在其他项目里反复验证过:

不要迷信 TCP 万能。
TCP 只解决网络层的丢包重传和拥塞控制,不负责应用层的收发速率匹配。高速、不对称链路场景下,应用层必须自己做发送节奏管控——确认上一批发出了再推下一批。换了协议只是换了一组问题,真正要修的是应用层对底层状态的感知能力。

这件事的通用形式是:任何跨网数据传输,只要带宽不对称且速率高,应用层必须实现某种形式的背压,不能假设 TCP 会替你搞定一切。

双通道协议里,控制通道与数据通道的时序没有天然保证。
GB28181 的 SIP 信令和 RTP 媒体走两套独立通道,SIP 畅通不代表 RTP 也畅通。下游"发完"和上游"收完"之间在不对称链路上可以差几十到几百毫秒。

结束类信令的发送时机必须绑定数据通道的实际完成状态,而不能绑定"我写完了"这个应用层事件。 这个原则适用于所有控制面与数据面分离的协议——不只是 GB28181。

前置故障会完全掩盖后续故障。

http://www.cnnetsun.cn/news/3576454.html

相关文章:

  • C++高性能内存池实现:从原理到实践,性能提升7倍
  • 调查问卷设计核心技巧与实战经验
  • TensorFlow Serving生产级部署与性能优化指南
  • cppimport:Python与C++混合编程的自动化构建利器
  • 上海非营业性客车额度拍卖政策解析与竞拍指南
  • C++11随机数库深度解析:从引擎分布到实战应用
  • n8n构建科技新闻自动化工作流实战指南
  • 一口气学会Linux的基础操作
  • 键盘鼠标操作录制器一款简单易用的电脑重复动作脚本回放制作软件
  • linux入门基础
  • 7月21日打卡
  • Linux基础及命令合集
  • 苹果M6芯片战略调整与2nm工艺技术解析
  • 高性能定时器设计:时间轮算法原理与C++实现详解
  • P2PKH:比特币的「哈希金库」与比特鹰的技术揭秘
  • Python编程入门:从“录取排名”题掌握排序算法与数据处理思维
  • 科技反弹,空头平仓!
  • AI学术写作工具:提升科研效率的智能解决方案
  • Unity视频无缝切换:双播放器预加载与渲染管线优化实战
  • AI写作工具对比:千笔AI与学术猹如何提升论文效率
  • 嵌入式电源管理核心:PSC模块状态机与低功耗实战指南
  • MuMu模拟器5.0跨平台技术解析与性能优化
  • 信奥刷题实战:从Chess问题看BFS算法与C++实现
  • Agent 实操入门 04:怎么跟 Agent 说话,它才能一次就听懂 —— Prompt 指令写作入门
  • 脊柱3D动态形变采集:MinkTec柔性弯曲形变传感器解决真实场景脊柱科研痛点
  • 大语言模型提示技术:从零样本到多轮对话实战指南
  • 人生大道至简的庖丁解牛
  • 元初混沌数学通用解题标准流程(溯源→分层→阴阳量化→维度校正→矛盾消解)
  • Magenta Systems Delphi Internet Component Suite (ICS) 扩展组件介绍
  • LangChain4j与Prompt工程在Java中的实战应用