目录
- Forward集群原理
- RTMP流转发(Forward)部署实例
- 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配置⽂件
- 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配置文件
- 复制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++音视频学习资料包、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓
3. 验证是否部署成功
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集群源码分析
-
从原理上来分析,要实现forward功能:
-
读取配置⽂件获取forward server的地址
-
创建RTMP推流客户端
-
从source⾥⾯拉取消息,然后推送给forward server
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打断点进行分析:
- 使用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操作。
-
主要逻辑在:SrsForwarder::forward()文章来源:https://www.toymoban.com/news/detail-410805.html
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?)
本文福利, 免费领取C++音视频学习资料包、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓文章来源地址https://www.toymoban.com/news/detail-410805.html
到了这里,关于SRS流媒体服务器——Forward集群搭建和源码分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!