• SRS流媒体服务器——Forward集群搭建和源码分析


    目录

     

    1. Forward集群原理
    2. RTMP流转发(Forward)部署实例
    3. Forward集群源码分析

    1. Forward集群原理

    Forward 表示向前、前头的、发送等意思。

    在SRS中可以理解为把Master节点获得直播流⼴播(转发)给所有的Slave节点,master节点由多少路直播流,那么在每个slave节点也会多少路直播流。

    注:在SRS中还有另外⼀种集群⽅式,edge⽅式。注意两种⽅式的⽤词不同。

    a. 在Forward模式中,中⼼节点叫Master,边缘节点叫Slave。

    b. 在edge模式中,中⼼节点叫origin(源站),边缘节点叫做edge。

    1. 适用场景

    Forward适合与搭建小型集群。

    推流者推流给master,那么master就会Forward到每一个Slave,那么在slave节点上不论需不需要都会有master过来的流。

    如果推流者的数量为10,那么master到slave之间的带宽就是:带宽=10 *slave的个数 *直播流码率,随着slave的增多,master的出口带宽会不断提高。

    而现实是,在某些slave节点其实没有人看,这样就造成了master到slave之间的带宽浪费。

    所以说Forward适合与搭建小型集群。

    2. RTMP流转发(Forward)部署实例

    SRS可以将送到SRS的流转发给其他RTMP服务器,实现简单集群/热备功能,也可以实现一路流热备

    a. 如编码器由于带宽限制,只能送一路流到RTMP服务器,要求RTMP服务器能将这路流也转发给其他RTMP备用服务器,实现主备容错集群

    假设服务器的IP是:8.141.75.248

    Forward就是SRS将流拷贝输出给其他的RTMP服务器,以SRS转发给SRS为例:

    • 主SRS:Master, 编码器推流到主SRS,主SRS将流处理的同时,将流转发到备SRS

    • 备SRS:Slave, 主SRS转发流到备SRS,就像编码器推送流到备用SRS一样。 我们的部署实例中,主SRS侦听1935端口,备SRS侦听19350端口。

    1. 编写主SRS配置⽂件

    1. vim conf/forward.master.conf
    1. # the config for srs to forward
    2. # @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
    3. # @see full.conf for detail config.
    4. listen 1935;
    5. max_connections 1000;
    6. pid ./objs/srs.master.pid;
    7. vhost __defaultVhost__ {
    8. forward {
    9. enabled on;
    10. destination 127.0.0.1:19350 127.0.0.1:19351; #forward目的地址,增加一个19351端口
    11. }
    12. }

    2.启动srs服务器。

    ./objs/srs -c conf/forward.master.conf
    

    监听日志信息:tail -f ./objs/srs.log

    2. 编写从SRS配置文件

    1. 复制conf/forward.slave.conf到conf/forward.slave1.conf,conf/forward.slave2.conf。
    1. cp conf/forward.slave.conf conf/forward.slave1.conf
    2. cp conf/forward.slave.conf conf/forward.slave2.conf

    2.修改conf/forward.slave1.conf配置文件。

    1. # the config for srs to forward
    2. # @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
    3. # @see full.conf for detail config.
    4. listen 19350; #注意端口
    5. max_connections 1000;
    6. pid ./objs/srs.slave1.pid; #./objs/srs.slave.pid改为./objs/srs.slave1.pid
    7. srs_log_tank file;
    8. srs_log_file ./objs/srs.slave1.log;
    9. vhost __defaultVhost__ {
    10. }

    3.修改conf/forward.slave2.conf配置文件。

    1. # the config for srs to forward
    2. # @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
    3. # @see full.conf for detail config.
    4. listen 19351;
    5. max_connections 1000;
    6. pid ./objs/srs.slave2.pid;
    7. srs_log_tank file;
    8. srs_log_file ./objs/srs.slave2.log;
    9. vhost __defaultVhost__ {
    10. }

    4.启动slave1和slave2

    1. ./objs/srs -c conf/forward.slave1.conf
    2. ./objs/srs -c conf/forward.slave2.conf
    3. 监听日志信息:tail -f ./objs/srs.log

    5.启动srs后查看srs是否启动成功:netstat -anp|grep srs

    本文结尾底部,领取最新最全C++音视频学习提升资料,内容包括(C/C++Linux 服务器开发,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓文章底部

    3. 验证是否部署成功

    1. 启动推流编码器

    1. 使用FFmpeg进行推流
    ffmpeg -re -i source.200kbps.768x320.flv -vcodec copy -acodec copy -f flv -y rtmp://8.141.75.248/live/livestream
    

    2.涉及到的流包括:

    1. 编码器推送的流:rtmp://8.141.75.248/live/livestream
    2. 主SRS转发的流:rtmp://8.141.75.248:19350/live/livestream
    3. 主SRS转发的流:rtmp://8.141.75.248:19351/live/livestream
    4. 观看主SRS的流:rtmp://8.141.75.248/live/livestream
    5. 观看从1 SRS的流:rtmp://8.141.75.248:19350/live/livestream
    6. 观看从2 SRS的流:rtmp://8.141.75.248:19351/live/livestream

    2. 观看主从SRS的RTMP流

    主RTMP流地址为:rtmp://8.141.75.248/live/livestream

    从1 SRS的流:rtmp://8.141.75.248:19350/live/livestream

    从2 SRS的流:rtmp://8.141.75.248:19351/live/livestream

    可以使用VLC观看或者SRS播放器播放:srs播放器

    注意:19350和19351端口需要在服务器开放,不然从节点无法拉流

    3. Forward集群源码分析

    1. 从原理上来分析,要实现forward功能:

    2. 读取配置⽂件获取forward server的地址

    3. 创建RTMP推流客户端

    4. 从source⾥⾯拉取消息,然后推送给forward server

    1. 从配置文件开始分析

    1. 打开 conf/forward.master.conf 配置文件。
    1. listen 1935;
    2. max_connections 1000;
    3. pid ./objs/srs.master.pid;
    4. srs_log_tank file;
    5. srs_log_file ./objs/srs.master.log;
    6. vhost __defaultVhost__ {
    7. forward {
    8. enabled on;
    9. destination 127.0.0.1:19350 127.0.0.1:19351;
    10. }
    11. }
    12. 日志打印在终端设置方法:
    13. #srs_log_tank file;
    14. #srs_log_file ./objs/srs.log;
    15. daemon off;
    16. srs_log_tank console;

    2.在srs_app_config.cpp中搜索“forward”即可发现读取“forward”的代码。

    1. bool SrsConfig::get_forward_enabled(string vhost)
    2. {
    3. static bool DEFAULT = false;
    4. SrsConfDirective* conf = get_vhost(vhost);
    5. if (!conf) {
    6. return DEFAULT;
    7. }
    8. conf = conf->get("forward");
    9. if (!conf) {
    10. return DEFAULT;
    11. }
    12. conf = conf->get("enabled");
    13. if (!conf || conf->arg0().empty()) {
    14. return DEFAULT;
    15. }
    16. return SRS_CONF_PERFER_FALSE(conf->arg0());
    17. }
    18. SrsConfDirective* SrsConfig::get_forwards(string vhost)
    19. {
    20. SrsConfDirective* conf = get_vhost(vhost);
    21. if (!conf) {
    22. return NULL;
    23. }
    24. conf = conf->get("forward");
    25. if (!conf) {
    26. return NULL;
    27. }
    28. return conf->get("destination");
    29. }

    2. 使用gdb打断点进行分析:

    1. 使用gdb打断点进行分析:
    1. gdb ./objs/srs
    2. (gdb) set args -c conf/forward.master.conf
    3. (gdb) b SrsConfig::get_forward_enabled(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    4. Breakpoint 1 at 0x53701d: file src/app/srs_app_config.cpp, line 4837.
    5. (gdb) b SrsConfig::get_forwards(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    6. Breakpoint 2 at 0x5372df: file src/app/srs_app_config.cpp, line 4859.

    2.推流后才能进行调试:

    ffmpeg -re -i source.200kbps.768x320.flv -vcodec copy -acodec copy -f flv -y rtmp://8.141.75.248/live/livestream
    

    3.SrsConfig::get_forward_enabled 对应调试信息:

    1. Breakpoint 1, SrsConfig::get_forward_enabled (this=0xa0fcf0, vhost="__defaultVhost__") at src/app/srs_app_config.cpp:4837
    2. 4837 {
    3. (gdb) bt
    4. #0 SrsConfig::get_forward_enabled (this=0xa0fcf0, vhost="__defaultVhost__") at src/app/srs_app_config.cpp:4837
    5. #1 0x00000000004e277a in SrsOriginHub::create_forwarders (this=0xab8000) at src/app/srs_app_source.cpp:1467
    6. #2 0x00000000004e1214 in SrsOriginHub::on_publish (this=0xab8000) at src/app/srs_app_source.cpp:1120
    7. #3 0x00000000004e76ce in SrsSource::on_publish (this=0xab7cd0) at src/app/srs_app_source.cpp:2457
    8. #4 0x00000000004d96ca in SrsRtmpConn::acquire_publish (this=0xa9be50, source=0xab7cd0) at src/app/srs_app_rtmp_conn.cpp:940
    9. #5 0x00000000004d874c in SrsRtmpConn::publishing (this=0xa9be50, source=0xab7cd0) at src/app/srs_app_rtmp_conn.cpp:822
    10. #6 0x00000000004d5ee7 in SrsRtmpConn::stream_service_cycle (this=0xa9be50) at src/app/srs_app_rtmp_conn.cpp:534
    11. #7 0x00000000004d4ddf in SrsRtmpConn::service_cycle (this=0xa9be50) at src/app/srs_app_rtmp_conn.cpp:388
    12. #8 0x00000000004d3ba7 in SrsRtmpConn::do_cycle (this=0xa9be50) at src/app/srs_app_rtmp_conn.cpp:209
    13. #9 0x00000000004d1d99 in SrsConnection::cycle (this=0xa9bec8) at src/app/srs_app_conn.cpp:171
    14. #10 0x000000000050ab08 in SrsSTCoroutine::cycle (this=0xa9c130) at src/app/srs_app_st.cpp:198
    15. #11 0x000000000050ab7d in SrsSTCoroutine::pfn (arg=0xa9c130) at src/app/srs_app_st.cpp:213
    16. #12 0x00000000005bed1a in _st_thread_main () at sched.c:337
    17. #13 0x00000000005bf492 in st_thread_create (start=0x5be696 <_st_vp_schedule+170>, arg=0x700000001, joinable=1, stk_size=1) at sched.c:616
    18. Backtrace stopped: previous frame inner to this frame (corrupt stack?)

    4.forward metadata,video,audio数据。

    1. b SrsForwarder::on_meta_data(SrsSharedPtrMessage*)
    2. (gdb) bt
    3. #0 SrsForwarder::on_meta_data (this=0xab9e60, shared_metadata=0xb28490) at src/app/srs_app_forward.cpp:114
    4. #1 0x00000000004df741 in SrsOriginHub::on_meta_data (this=0xab8000, shared_metadata=0xb28490, packet=0xb283f0) at src/app/srs_app_source.cpp:924
    5. #2 0x00000000004e5e23 in SrsSource::on_meta_data (this=0xab7cd0, msg=0xb28210, metadata=0xb283f0) at src/app/srs_app_source.cpp:2113
    6. #3 0x00000000004d9e93 in SrsRtmpConn::process_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:1045
    7. #4 0x00000000004d9aa6 in SrsRtmpConn::handle_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:993
    8. #5 0x0000000000582720 in SrsPublishRecvThread::consume (this=0xab6480, msg=0xb28210) at src/app/srs_app_recv_thread.cpp:389
    9. #6 0x000000000058123e in SrsRecvThread::do_cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:146
    10. #7 0x000000000058108f in SrsRecvThread::cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:115
    11. #8 0x000000000050ab08 in SrsSTCoroutine::cycle (this=0xb024f0) at src/app/srs_app_st.cpp:198
    12. #9 0x000000000050ab7d in SrsSTCoroutine::pfn (arg=0xb024f0) at src/app/srs_app_st.cpp:213
    13. #10 0x00000000005bed1a in _st_thread_main () at sched.c:337
    14. #11 0x00000000005bf492 in st_thread_create (start=0xab8290, arg=0xab61b0, joinable=0, stk_size=11231648) at sched.c:616
    15. Backtrace stopped: previous frame inner to this frame (corrupt stack?)
    1. b SrsForwarder::on_video(SrsSharedPtrMessage*)
    2. (gdb) bt
    3. #0 SrsForwarder::on_video (this=0xab9e60, shared_video=0xb13080) at src/app/srs_app_forward.cpp:155
    4. #1 0x00000000004e1037 in SrsOriginHub::on_video (this=0xab8000, shared_video=0xb13080, is_sequence_header=true) at src/app/srs_app_source.cpp:1106
    5. #2 0x00000000004e6c59 in SrsSource::on_video_imp (this=0xab7cd0, msg=0xb13080) at src/app/srs_app_source.cpp:2303
    6. #3 0x00000000004e68ad in SrsSource::on_video (this=0xab7cd0, shared_video=0xb28210) at src/app/srs_app_source.cpp:2258
    7. #4 0x00000000004d9c7f in SrsRtmpConn::process_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:1021
    8. #5 0x00000000004d9aa6 in SrsRtmpConn::handle_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:993
    9. #6 0x0000000000582720 in SrsPublishRecvThread::consume (this=0xab6480, msg=0xb28210) at src/app/srs_app_recv_thread.cpp:389
    10. #7 0x000000000058123e in SrsRecvThread::do_cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:146
    11. #8 0x000000000058108f in SrsRecvThread::cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:115
    12. #9 0x000000000050ab08 in SrsSTCoroutine::cycle (this=0xb024f0) at src/app/srs_app_st.cpp:198
    13. #10 0x000000000050ab7d in SrsSTCoroutine::pfn (arg=0xb024f0) at src/app/srs_app_st.cpp:213
    14. #11 0x00000000005bed1a in _st_thread_main () at sched.c:337
    15. #12 0x00000000005bf492 in st_thread_create (start=0xab8290, arg=0xab61b0, joinable=0, stk_size=11231648) at sched.c:616
    16. Backtrace stopped: previous frame inner to this frame (corrupt stack?)
    1. b SrsForwarder::on_audio(SrsSharedPtrMessage*)
    2. (gdb) bt
    3. #0 SrsForwarder::on_audio (this=0xab9e60, shared_audio=0xb13090) at src/app/srs_app_forward.cpp:132
    4. #1 0x00000000004e02d9 in SrsOriginHub::on_audio (this=0xab8000, shared_audio=0xb13090) at src/app/srs_app_source.cpp:1013
    5. #2 0x00000000004e644e in SrsSource::on_audio_imp (this=0xab7cd0, msg=0xb13090) at src/app/srs_app_source.cpp:2188
    6. #3 0x00000000004e6051 in SrsSource::on_audio (this=0xab7cd0, shared_audio=0xb28210) at src/app/srs_app_source.cpp:2138
    7. #4 0x00000000004d9c00 in SrsRtmpConn::process_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:1014
    8. #5 0x00000000004d9aa6 in SrsRtmpConn::handle_publish_message (this=0xa9be50, source=0xab7cd0, msg=0xb28210) at src/app/srs_app_rtmp_conn.cpp:993
    9. #6 0x0000000000582720 in SrsPublishRecvThread::consume (this=0xab6480, msg=0xb28210) at src/app/srs_app_recv_thread.cpp:389
    10. #7 0x000000000058123e in SrsRecvThread::do_cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:146
    11. #8 0x000000000058108f in SrsRecvThread::cycle (this=0xab6488) at src/app/srs_app_recv_thread.cpp:115
    12. #9 0x000000000050ab08 in SrsSTCoroutine::cycle (this=0xb024f0) at src/app/srs_app_st.cpp:198
    13. #10 0x000000000050ab7d in SrsSTCoroutine::pfn (arg=0xb024f0) at src/app/srs_app_st.cpp:213
    14. #11 0x00000000005bed1a in _st_thread_main () at sched.c:337
    15. #12 0x00000000005bf492 in st_thread_create (start=0xab8290, arg=0xab61b0, joinable=0, stk_size=11231648) at sched.c:616
    16. Backtrace stopped: previous frame inner to this frame (corrupt stack?)

    5.SrsForwarder::do_cycle() 完成建联,推流到slave操作。

    1. 主要逻辑在:SrsForwarder::forward()

    1. b SrsForwarder::forward()
    2. (gdb) bt
    3. #0 SrsForwarder::forward (this=0xab9e60) at src/app/srs_app_forward.cpp:248
    4. #1 0x00000000004f8648 in SrsForwarder::do_cycle (this=0xab9e60) at src/app/srs_app_forward.cpp:237
    5. #2 0x00000000004f7fd7 in SrsForwarder::cycle (this=0xab9e60) at src/app/srs_app_forward.cpp:190
    6. #3 0x000000000050ab08 in SrsSTCoroutine::cycle (this=0xab9c20) at src/app/srs_app_st.cpp:198
    7. #4 0x000000000050ab7d in SrsSTCoroutine::pfn (arg=0xab9c20) at src/app/srs_app_st.cpp:213
    8. #5 0x00000000005bed1a in _st_thread_main () at sched.c:337
    9. #6 0x00000000005bf492 in st_thread_create (start=0xab8290, arg=0xab61b0, joinable=0, stk_size=11231648) at sched.c:616
    10. Backtrace stopped: previous frame inner to this frame (corrupt stack?)

    原文链接:SRS流媒体服务器——Forward集群搭建和源码分析 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛

    本文结尾底部↓↓↓,领取最新最全C++音视频学习提升资料,内容包括(C/C++Linux 服务器开发,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓

  • 相关阅读:
    Docker02:名词解释与安装
    DNS域名解析轮询过程图解
    如何打造新时代的终端播放产品?
    ChatGPT调教指南 | 咒语指南 | Prompts提示词教程(一)
    notepad++去除每一行第二个等号之后的内容解决ResolvePackageNotFound
    零束科技打通智驾全域数据闭环,加速智驾场景规模化量产落地!
    【Java】Jsoup格式化html问题(文本空格折叠等)解决方法
    milvus Delete API流程源码分析
    Java 如何判断Map集合中是否包含元素呢?
    力扣每日一题:1822:数组元素积的符号【模拟思维题】
  • 原文地址:https://blog.csdn.net/m0_60259116/article/details/125434195