点赞
评论
收藏
分享
举报
nginx-rtmp-module 存在的问题
发表于2020-09-17 01:16

浏览 2k

        RTMP 是 Real-Time Messaging Protocol 的简写,它是 Adobe 于 2009 年公开的一个实时音视频传输协议(目前 Adobe 官网上的 RTMP 规范文档发布时间是 2012 年 12 月)。

        RTMP 是基于 TCP 的协议,当然它也有基于 UDP 的变种。Flash 流行的年代,可以在客户端和服务器之间很方便地使用 RTMP 来连传输实时音视频信息,其延迟为 1~3 秒。Flash 现在已经式微,现在主流的浏览器几乎都已经默认关闭了 Flash 。Adobe 早在 2017 年就已经宣布到 2020 年底不再支持 Flash 。

        有很多人担心 Flash 彻底凉透后,RTMP 是否也会式微?个人觉得近几年不用担心,Flash 与 RTMP 的关系有点类似于 Unix 和 C 语言的关系,现在用到 Unix 的地方已经非常少,但是 C 语言却依然无处不在。现在很多厂商的直播协议中,RTMP 依然占据很重要的地位。

        开源的 RTMP 服务器有很多,nginx-rtmp-module (说句题外话,nginx-rtmp-module 的作者目前供职于 NGINX, Inc.,至于是他先写了这个模块再去的 NGINX, Inc. 还是去了 NGINX, Inc. 再写的这个模块就不得而知了)是其中一个非常流行的实现,它依托 Nginx,也继承了 Nginx 优秀的高并发能力和高可扩展性。网上很多对比单进程条件下各种 RTMP 服务器的并发能力(包括推流和播放)是不客观的,Nginx 天生就是多进程实现,虽然其因为架构设计的问题,进程个数的增加对推流并发能力的提升到了一定数量级后就无效了,但是其播放并发能力是随着进程个数增加而增加的。

        nginx-rtmp-module 的作者实现了开创性的工作,但是遗憾的是,他从 2017 年底就已经不再维护该项目。nginx-rtmp-module 本身也有很多问题,如果要用在生产环境中,需要进行大量修改。而且,随着社会发展,nginx-rtmp-module 也已经不能满足越来越多样化的需求。本文只讲解 nginx-rtmp-module 本身到目前为止还存在的问题,能力有限,只挑出我看得懂的地方讲解。

1. Typo 问题,见 #527 。

可能是复制粘贴的过程中发生错误,发送的 ABORT 命令被写成了 CHUNK_SIZE 命令了。

2. on_publish 回调无法修改流的名称,见 #713 和 #777 。

on_publish 可以回调 HTTP 请求,返回一个 302 和 Location 指明修改流的名称,但是这个功能对 HLS 和 DASH 模块无效。

3. 用错函数的问题,见 #845 。

原因可能跟 1 一样,一个本来需要设置数字的函数的地方,却写了一个设置字符串的函数。

4. 解析问题,见 #1014 。

按照该网友的说法,幸好 nginx-rtmp-module 没用到 srv 和 app 里的配置,而 main 的配置在几个级别都是指向同一个配置(表达能力有限,详细的结构可参考陶辉大神的《深入理解 Nginx 模块开发与架构解析 第 2 版 P354~P364》,不完全相同,但是 main 和 srv 是一样的),所以没有问题。但是如果要用到 srv 和 app 里的配置,就需要注意不同的级别里的 srv 和 app 的配置可能不一样,必须按照该网友的方法修改才行。

5. 以多进程方式运行 Nginx + nginx-rtmp-module 时,开启手动录制推流配置,可能丢失录制的流名称,见 #1249 。

接收录制命令的进程和接收推流的进程不是同一个进程就会造成这个问题。

6. 栈溢出问题,见 #1275 。

开 DEBUG 可能崩掉。

7. 向缓冲区插入数据的位置计算公式错误,见 ngx_rtmp_handler.c 中 ngx_rtmp_send_message 函数:

        nmsg = (s->out_last - s->out_pos) % s->out_queue + 1;

其中 out_queue 是输出缓冲区的大小,out_pos 和 out_last 分别指向缓冲区数据输出和输入的位置。如果 out_pos out_last 时(网络不畅通,缓冲数据),得到的结果是负的,造成后面本应该丢帧的逻辑不满足,也就是说不但不丢帧以保证减少数据发送,还使足了劲儿发。

8. 不支持省略 listen 配置项。

如果省略 listen 配置项,整个模块不工作,因为它根本就不监听任何默认端口(RTMP 默认端口 1935)。这个可能很多人都觉得要求过于严苛,但是你架不住就有沙雕网友这么玩。

9. 开启 wait_video 或者 wait_key 选项后,无法播放推送的纯音频流。

nginx-rtmp-module 没有判断收到的流里面有没有视频信息,如果开启了这两个选项其中之一,它就会傻等着视频帧或者视频 I 帧,客户端请求的流它都给 continue 了,就是不发送数据。

10. 如果在 edge 服务器和 origin 服务器上都开启了 meta copy; 时,edge 服务器上的流无法播放。

edge 服务器在解析上游发送的 meta 信息时,多移动了一个偏移量,导致无法正确解析。

11. 内存泄露问题。

主要是在 ngx_rtmp_core_module.c 和 ngx_rtmp_live_module.c 两个文件中,创建了内存池但是没有销毁操作。

12. 编译错误。

这个错误有很多,在类 Unix 系统上,主要是比较新的编译器将 switch 中某个 case 没有 break 视为错误。还有在 Windows 平台上使用比较新的编译器,如 VS 2013 以及以上版本也会有编译错误。

        其实 nginx-rtmp-module 还有其他的一些问题,有些是我忘了,有些是能力有限看不懂。

        nginx-rtmp-module 在 Flash 流行的年代无疑是一个非常优秀的 RTMP 服务器实现。但是随着 Flash 的衰落和直播行业的发展,其设计的缺陷和缺少的功能导致它被越来越多的后起之秀超越。但是不管怎么说,从 1 到 100 的难度终究还是比不上 0 到 1 的难度,所谓无路难,开路更难,后来者或多或少都会借鉴它的一些实现细节,有些实现思路可以用到更通用的领域中。

        最后,上述的问题,已经在我的开源项目 nginx-http-flv-module 中全部解决了,并且添加了一些额外的功能。已有很多个人和公司使用 nginx-http-flv-module,目前仍在维护,欢迎大家使用,提交 issue 和 PR。


已修改于2023-03-09 03:51
本作品系原创
创作不易,留下一份鼓励
winshining1202

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
winshining1202
这家伙很懒还未留下介绍~
2
文章
0
问答
3
粉丝
相关文章
这其实是nginx-rtmp-module的缺陷分析系列文章的第四篇了,之前的三篇在本站建立之前已经发布在了其他网站上。Nginx 一般情况下都是以多进程方式(一个master进程和多个worker进程)运行的,但是 nginx-rtmp-module 模块对多进程方式的支持很不成熟。前面的文章提到过以多进程方式运行Nginx时,由于 nginx-rtmp-module本身不支持Vhost功能,再加上它使用Unixdomainsocket(没有端口信息)转发媒体流到其他的worker进程,导致其他的worker进程无法知道转发的媒体流需要匹配的是哪个server配置。Nginx从 1.9.11版本开始,在类Unix系统上支持将第三方模块编译成动态模块,可以在运行时加载它们。这又引出多进程方式下运行nginx-rtmp-module的另一个问题。这个问题产生的背景是:用户A开发了自己的第三方模块(不开源),用户B在nginx-rtmp-module的基础上开发了一些新的功能(
点赞 4
浏览 1.1k
1.安装依赖yuminstall-yreadline-develncurses-devel2.安装Lua#tarxflua-5.1.5.tar.gz #cdlua-5.1.5 #makelinux #makeinstall3.安装LuaJIT#wgethttp://luajit.org/download/LuaJIT-2.0.4.tar.gz #tarxfLuaJIT-2.0.4.tar.gz #cdLuaJIT-2.0.4 #make&&makeinstall4.安装两个插件#wgethttps://codeload.github.com/simpl/ngx_devel_kit/zip/master #unzipngx_devel_kit-master.zip #cp-rngx_devel_kit-master/usr/local/ #wgethttps://github.com/openresty/lua-nginx-module#readme #unziplua-nginx-modu
点赞 3
浏览 1.2k
NGINX Ingress Controller 版本更新到 3.0.2🎉该版本允许将 OnDelete 用作策略值🚀确保未就绪的 endpoint 不会被添加到 upstream✨了解更多: h
点赞 1
浏览 715