srs之与nginx-rtmp性能对比

本文深入探讨SRS(SimpleRtmpServer)单进程实现9000并发,比nginx-rtmp高三倍的秘诀。通过st-load、gperf/gprof性能分析、引用计数避免内存拷贝、writev发送chunked包、mw(merged-write)技术等关键点,详细解析SRS如何优化性能。同时,比较nginx-rtmp与SRS的性能差异,提供性能测试链接与优化commit参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文转载
SRS(Simple Rtmp Server)单进程能支持9000并发,nginx-rtmp单进程最多支持3000个,单进程的性能SRS(Simple Rtmp Server)是nginx-rtmp的三倍。SRS(Simple Rtmp Server)单进程性能如何做到nginx-rtmp的三倍的?SRS(Simple Rtmp Server)哪几个结构极大提升了性能?先来看看我们遇到的问题,RTMP协议和HTTP协议是又很大不同的。nginx在分发HLS,即m3u8文本文件和ts视频文件时,对所有连接发送的都是同一个内容,甚至可以调用sendfile让内核自己发fd去,nginx服务器自己要干的事情很少了;如果nginx必须把每个ts的内容读出来,修改里面某些字节,然后每个客户端一次发送的数据前还得加点什么,nginx就会很忙了。这就是RTMP,每个video或audio包,在发送给某个连接之前,都得修改下时间戳(至少FMS是每个连接收到的媒体数据都是从0开始的时间戳),然后把包再拆分成一些小片段(chunked),每个chunk包前面加几个字节的头信息,然后发送。我勒个去~举个例子,假设有个视频的I帧有200000bytes,默认的chunk包最大是128字节,所以得拆分成200000/128=1562个chunk包来发送,每个chunk包前面都要加chunk头。没有办法sendfile了吧?可以想象得到内存要被蹂躏成什么样子吧?这就是RTMP流媒体服务器麻烦的地方了,客官可以自己想下搞个什么样子的算法能最高效发送粗去~nginx-rtmp是性能最高的服务器,比crtmpd都要高,red5根本就低两个级别,wowza也没有它高。SRS(Simple Rtmp Sever)做了什么能够比nginx-rtmp单进程还要高三倍?第一点,st-load,这个是SRS(Simple Rtmp Sever)能做到高性能的最重要的原因,一个st-load可以模拟2000+的客户端。一个牛逼的benchmark的工具;如果没有st-load,如何知道系统的性能瓶颈在哪里?总不能打开3000个flash页面播放rtmp流吧?开启3000个ffmpeg来抓流?不靠谱。这就是高性能第一定律:高性能不是想象和猜测粗来的,而是测试、调试和改进粗来的。第二点,gperf/gprof性能benchmark功能。在编译SRS(Simple Rtmp Sever)时,就可以打开gcp或者gprof的性能分析选项,灰常方便就可以拿到数据。缩短了改进和优化的开发周期。第三点,引用计数的msgs避免内存拷贝。从编码器收到的video/audio数据,转换成SrsSharedPtrMessage放到每个连接的发送队列,避免每个都拷贝一次;因为发送给每个客户端的消息(不是chunked包)头可能不一样,譬如时间戳不一样,但是消息的payload是一样的。第四点,使用writev发送chunked包,避免消息到chunked包的内存拷贝。可以开辟一个header的缓冲区,专门放每个chunked包的header,然后用iovc保存头的指针和大小,payload的指针和大小,用writev就可以一次发送。第五点,mw(merged-write)技术,即一次发送多个消息。虽然每个消息使用writev可以避免拷贝,还有更高效的是一次发送多个消息,即把多个消息的chunked头写在header的缓冲区,iovc保存多个消息的chunked头和payload指针,一次writev发送多个消息。这个是最关键所在。第六点,减少timeout recv,每个连接都是一个st-thread在服务。在发送之前,线程得尝试从连接收取消息,譬如客户端的stop之类的;所以只能recv时指定timeout,譬如300毫秒如果还没有收到消息,就发送连接队列中的消息。这个会导致st的timeout红黑树操作频繁。实际上,可以直接开启一个recv线程,因为客户端的消息非常少,避免timeout接收。第七点,fast buffer和cache。譬如每次取消息的数组,使用cache;使用fast buffer避免频繁删除;使用header的cache。第八点,vector还是list?有的地方看起来list更高效,譬如simple buffer这种频繁删除头,以及在结尾加入数据,看起来是list应该做的事情。但是实际上测试发现,vector比list高10%性能。所以,回到第一点,高性能不是猜测和想象粗来的;有的时候有些代码写得很慢,但是这个频率非常低,那么就不要考虑性能,而要考虑可读性。我觉得可以算是高性能第二定律:不要总是考虑高性能,可读性更重要。另外,nginx-rtmp有多进程啦。没错,可惜SRS(Simple Rtmp Sever)也可以有多进程啦;可以有为何没有做呢?首先,9000个连接还不够么?1Mbps的码率可以到9Gbps了哦,伦家的机房交换机有那么牛逼么?敢一个服务器服务那么多用户么?其次,多进程不是万金油的,不过是一种技术,不是没有多进程就低人一等,有了多进程就高人一等,别那么技术控,关键在于对于客户有啥价值。再次,可以用RTMP302支持多进程,这个是最稳定的多进程技术。最后,杰哥的BLS已经实现了多进程,他设计的多进程架构,即一个源站fork多个边缘的进程的结构,是最简单的多进程通信模型。这可以引申出高性能第三定律:表当真呢,高性能不是万金油。SRS(Simple Rtmp Server)的性能测试,请参考:https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_PerformanceSRS(Simple Rtmp Server)的性能优化commit,请参考:https://github.com/winlinvip/simple-rtmp-server/tree/2.0release#performance
<think>嗯,用户已经搭建好了SRS服务器,现在需要实现接收RTMP推流并进行转码,然后生成HLS切片。首先,我需要确认用户对SRS的配置是否了解,尤其是转码和HLS相关的部分。可能用户已经安装了SRS,但需要调整配置文件来启用这些功能。 接下来,转码部分。SRS本身支持通过FFmpeg进行转码,所以用户需要在配置文件中指定转码参数。比如,将1080p转为720p,需要设置视频的分辨率、码率、编码格式等。这里可能需要指导用户如何编写正确的FFmpeg命令或SRS的转码配置,确保参数正确无误,比如使用libx264编码器,调整分辨率为1280x720,设置合适的码率和帧率。 然后是生成HLS切片。SRS有内置的HLS支持,用户需要配置切片时长、路径、保留切片数量等参数。需要提醒用户检查HLS的输出目录是否正确,是否有写入权限,以及生成的m3u8文件能否被web服务器正确访问。此外,可能还需要配置跨域问题,确保网页播放时不会遇到阻碍。 另外,用户可能还需要在转码后如何验证效果,比如使用FFmpeg或VLC检查视频分辨率和质量是否正确,HLS切片是否按时生成,以及通过浏览器测试m3u8播放是否流畅。需要考虑到用户可能会遇到的常见问题,比如配置文件错误、路径权限问题、端口被占用等,提前给出排查建议。 最后,确保整个流程的步骤清晰,从修改配置文件到重启服务,再到推流测试,每一步都明确。可能需要给出示例配置代码,让用户可以直接复制粘贴,并根据自己的环境调整参数。同时,强调关键点,如转码参数的正确性、HLS配置的注意事项,以及测试方法,帮助用户顺利完成部署。</think>好的,我来帮你梳理实现流程。根据你已经搭建好SRS服务器的基础,以下是实现RTMP接收+转码+HLS生成的分步操作: --- ### 一、SRS服务器配置修改 #### 1. 配置文件路径 - 默认路径:`/usr/local/srs/conf/srs.conf` - 添加以下核心配置段: ```nginx # RTMP接收配置 listen 1935; max_connections 1000; daemon off; srs_log_tank console; vhost __defaultVhost__ { # 转码配置(1080P→720P) transcode { enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine ff { enabled on; vfilter { # 缩放滤镜(调整分辨率) vf scale=1280:-1; } vcodec libx264; vbitrate 1500; vfps 30; vwidth 1280; vheight 720; vthreads 4; vprofile main; vpreset medium; vparams { # 关键帧间隔(影响HLS切片) x264opts force_keyframe=expr:gte(n,n_forced*50); } acodec aac; abitrate 128; asample_rate 44100; achannels 2; aparams { } output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; } } # HLS切片生成配置 hls { enabled on; hls_fragment 10; # 切片时长(秒) hls_window 60; # 保留切片总时长(秒) hls_path ./objs/nginx/html/hls; # 切片存储路径 hls_m3u8_file [app]/[stream].m3u8; hls_ts_file [app]/[stream]-[seq].ts; hls_cleanup on; # 自动清理旧切片 } } ``` --- ### 二、关键参数说明 #### 1. 转码参数 - `scale=1280:-1`:保持宽高比缩放至1280宽度(自动计算高度) - `vbitrate=1500`:视频码率1500kbps - `vpreset=medium`:编码速度质量的平衡点 - `force_keyframe`:强制关键帧间隔,确保HLS切片对齐 #### 2. HLS参数 - `hls_fragment 10`:每个.ts切片10秒 - `hls_window 60`:保留最近60秒内容(即6个切片) --- ### 三、操作流程 1. **重启SRS服务** ```bash sudo systemctl restart srs # 或直接运行 ./objs/srs -c conf/srs.conf ``` 2. **推流测试** ```bash # 使用FFmpeg模拟推流(分辨率需≥1080P) ffmpeg -re -i input.mp4 -c copy -f flv rtmp://your_server_ip:1935/live/streamkey ``` 3. **验证转码结果** ```bash # 查看转码后的RTMP流 ffplay rtmp://your_server_ip:1935/live/streamkey_ff # 检查HLS切片生成 ls ./objs/nginx/html/hls/live/ # 应看到 streamkey_ff.m3u8 和 .ts文件 ``` 4. **Web播放配置** ```html <!-- 使用hls.js播放示例 --> <video id="video" controls></video> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <script> if(Hls.isSupported()) { const video = document.getElementById('video'); const hls = new Hls(); hls.loadSource('http://your_domain/hls/live/streamkey_ff.m3u8'); hls.attachMedia(video); } </script> ``` --- ### 四、常见问题排查 1. **分辨率未变化** - 检查`scale`参数是否正确 - 确认输入流分辨率确实≥1080P 2. **HLS切片未生成** - 检查`hls_path`目录权限(需可写) - 查看SRS日志是否有报错 ```bash tail -f ./objs/srs.log ``` 3. **播放卡顿** - 降低`vbitrate`值(如改为1000) - 调整`vpreset`为`fast` --- ### 五、进阶优化建议 1. **多码率自适应** ```nginx # 在transcode段添加多个engine配置 engine low { vwidth 640; vheight 360; vbitrate 800; } ``` 2. **CDN分发** - 将`hls_path`指向CDN同步目录 - 配置Nginx反向代理: ```nginx location /hls/ { alias /path/to/hls/; add_header Access-Control-Allow-Origin *; types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值