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
# the config for srs to forward
# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
# @see full.conf for detail config.

listen              1935;
max_connections     1000;
pid                 ./objs/srs.master.pid;
vhost __defaultVhost__ {
    forward {
        enabled on;
        destination 127.0.0.1:19350 127.0.0.1:19351; #forward目的地址,增加一个19351端口
    }
}

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。
cp conf/forward.slave.conf conf/forward.slave1.conf
cp conf/forward.slave.conf conf/forward.slave2.conf

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

# the config for srs to forward
# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
# @see full.conf for detail config.

listen              19350; #注意端口
max_connections     1000;
pid                 ./objs/srs.slave1.pid;  #./objs/srs.slave.pid改为./objs/srs.slave1.pid
srs_log_tank 		file;
srs_log_file 		./objs/srs.slave1.log;
vhost __defaultVhost__ {
}

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

# the config for srs to forward
# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleForward
# @see full.conf for detail config.

listen              19351;
max_connections     1000;
pid                 ./objs/srs.slave2.pid;
srs_log_tank 		file;
srs_log_file 		./objs/srs.slave2.log;
vhost __defaultVhost__ {
}

4.启动slave1和slave2

./objs/srs -c conf/forward.slave1.conf
./objs/srs -c conf/forward.slave2.conf


监听日志信息: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.涉及到的流包括:

编码器推送的流:rtmp://8.141.75.248/live/livestream

主SRS转发的流:rtmp://8.141.75.248:19350/live/livestream
主SRS转发的流:rtmp://8.141.75.248:19351/live/livestream

观看主SRS的流: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

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 配置文件。
listen              1935;
max_connections     1000;
pid                 ./objs/srs.master.pid;
srs_log_tank        file;
srs_log_file        ./objs/srs.master.log;
vhost __defaultVhost__ {
    forward {
        enabled on;
        destination 127.0.0.1:19350 127.0.0.1:19351;
    }
}

日志打印在终端设置方法:
#srs_log_tank        file;
#srs_log_file        ./objs/srs.log;
daemon              off;
srs_log_tank        console;

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

bool SrsConfig::get_forward_enabled(string vhost)
{
    static bool DEFAULT = false;
    
    SrsConfDirective* conf = get_vhost(vhost);
    if (!conf) {
        return DEFAULT;
    }
    
    conf = conf->get("forward");
    if (!conf) {
        return DEFAULT;
    }
    
    conf = conf->get("enabled");
    if (!conf || conf->arg0().empty()) {
        return DEFAULT;
    }
    
    return SRS_CONF_PERFER_FALSE(conf->arg0());
}

SrsConfDirective* SrsConfig::get_forwards(string vhost)
{
    SrsConfDirective* conf = get_vhost(vhost);
    if (!conf) {
        return NULL;
    }
    
    conf = conf->get("forward");
    if (!conf) {
        return NULL;
    }
    
    return conf->get("destination");
}

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

  1. 使用gdb打断点进行分析:
gdb ./objs/srs

(gdb) set args -c conf/forward.master.conf
(gdb) b SrsConfig::get_forward_enabled(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
Breakpoint 1 at 0x53701d: file src/app/srs_app_config.cpp, line 4837.
(gdb) b SrsConfig::get_forwards(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
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 对应调试信息:

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

4.forward metadata,video,audio数据。

b SrsForwarder::on_meta_data(SrsSharedPtrMessage*)

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

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

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

b SrsForwarder::forward()

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

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

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

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/125434195
今日推荐