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

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

目录

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

SRS安装部署相关内容:

  1. SRS流媒体服务器——单机环境搭建和源码目录介绍
  2. SRS流媒体服务器——Forward集群搭建和源码分析
  3. SRS流媒体服务器——Edge集群搭建
  4. SRS流媒体服务器——WebRTC推拉流演示
  5. SRS流媒体服务器——SRS4.0 WebRTC⼀对⼀通话环境搭建与逻辑分析

SRS部分源码分析相关内容:

  1. SRS流媒体服务器——基本流程简单分析
  2. SRS流媒体服务器——RTMP端⼝监听逻辑分析
  3. SRS流媒体服务器——RTMP推流、拉流创建连接
  4. SRS流媒体服务器——服务器读取RTMP推流数据
  5. SRS流媒体服务器——服务器给RTMP拉流端转发数据

1. Forward集群原理

  1. Forward 表示向前、前头的、发送等意思。
  2. 在SRS中可以理解为把Master节点获得直播流⼴播(转发)给所有的Slave节点,master节点由多少路直播流,那么在每个slave节点也会多少路直播流。
  3. 注:在SRS中还有另外⼀种集群⽅式,edge⽅式。注意两种⽅式的⽤词不同。
    a. 在Forward模式中,中⼼节点叫Master,边缘节点叫Slave。
    b. 在edge模式中,中⼼节点叫origin(源站),边缘节点叫做edge。

1. 适用场景

在这里插入图片描述

  1. Forward适合搭建⼩型集群。
  2. 推流者推流给master,那么master就会Forward到每⼀个Slave,那么在slave节点上不论需不需要都会有master过来的流。
  3. 如果推流者的数量为10,那么master到slave之间的带宽就是:带宽=10 *slave的个数 *直播流码率,随着slave的增多,master的出⼝带宽会不断提⾼。
  4. ⽽现实是,在某些slave节点其实没有⼈看,这样就造成了master到slave之间的带宽浪费。
  5. 所以说Forward适合⽤于搭建⼩型集群。

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

  1. SRS可以将送到SRS的流转发给其他RTMP服务器,实现简单集群/热备功能,也可以实现⼀路流热备
    a. 如编码器由于带宽限制,只能送⼀路流到RTMP服务器,要求RTMP服务器能将这路流也转发给其他RTMP备⽤服务器,实现主备容错集群。
  2. 假设服务器的IP是:8.141.75.248
  3. Forward就是SRS将流拷⻉输出给其他的RTMP服务器,以SRS转发给SRS为例:
    1. 主SRS:Master,编码器推流到主SRS,主SRS将流处理的同时,将流转发到备SRS。
    2. 备SRS:Slave,主SRS转发流到备SRS,就像编码器推送流到备⽤SRS⼀样。
    3. 测试部署的实例中,主SRS侦听1935端⼝,备SRS侦听19350和19351端⼝。

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端口
    }
}
  1. 启动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
  1. 修改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__ {
}
  1. 修改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__ {
}
  1. 启动slave1和slave2
./objs/srs -c conf/forward.slave1.conf
./objs/srs -c conf/forward.slave2.conf


监听日志信息:tail -f ./objs/srs.log
  1. 启动srs后查看srs是否启动成功:netstat -anp|grep 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
  1. 涉及到的流包括:
编码器推送的流: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流
  1. 主RTMP流地址为:rtmp://8.141.75.248/live/livestream
  2. 从1 SRS的流:rtmp://8.141.75.248:19350/live/livestream
  3. 从2 SRS的流:rtmp://8.141.75.248:19351/live/livestream
  4. 可以使用VLC观看或者SRS播放器播放:srs播放器
  5. 注意:19350和19351端口需要在服务器开放,不然从节点无法拉流

3. Forward集群源码分析

  1. 从原理上来分析,要实现forward功能:
    1. 读取配置⽂件获取forward server的地址
    2. 创建RTMP推流客户端
    3. 从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;
  1. 在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.
  1. 推流后才能进行调试:
ffmpeg -re -i source.200kbps.768x320.flv -vcodec copy -acodec copy -f flv -y rtmp://8.141.75.248/live/livestream
  1. 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?)
  1. 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?)
  1. 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?)
  1. 后续会补充更详细的代码分析和流程图,现在先自行根据调用stack看源码。
### SRS 4.0 WebRTC One-to-One Calling Setup and Logic Analysis #### Overview of Environment Configuration To establish a one-to-one calling environment using the SRS (Simple RTMP Server) version 4.0 with WebRTC support, several key components need to be configured properly. The server must handle both signaling for establishing peer connections as well as media streaming between peers[^1]. #### Detailed Steps for Setting Up SRS 4.0 WebRTC The process involves setting up an instance of SRS that supports WebRTC protocols specifically designed for real-time communication over web browsers or mobile applications. For configuring OBS Studio to push streams via RTMP protocol which can then be converted into WebRTC format suitable for browser-based playback: - Ensure OBS is set correctly to output video/audio data through RTMP. - Configure SRS so it listens on appropriate ports for incoming RTMP streams while also being capable of serving those streams outwards in WebRTC form[^2]. Once these configurations are completed successfully, users should have access to live audio/video feeds directly within their supported web clients without requiring additional software installations beyond what's necessary for modern HTML5-compliant websites. #### Understanding the Working Mechanism Behind SRS 4.0 WebRTC Calls In terms of how such calls function internally once everything has been set up appropriately: When initiating a call session, each participant’s device sends its local media stream description along with any required network information needed by other participants joining the conversation. This exchange happens outside direct control from SRS itself but rather relies upon external services like WebSocket servers handling SDP exchanges among parties involved before actual RTP packets start flowing across established ICE candidates paths negotiated during this initial handshake phase. After successful negotiation, all subsequent traffic related to voice chat or screen sharing will traverse back-and-forth seamlessly thanks largely due to efficient packet processing routines implemented inside core modules responsible not only for listening operations at designated IP addresses/ports pairs but also managing threads dedicated towards receiving/transmitting raw binary payloads containing encoded multimedia content intended ultimately for presentation purposes either visually or audibly depending on context-specific requirements outlined earlier when defining application scenarios involving interactive communications sessions facilitated primarily though not exclusively underpinned here today particularly focusing around implementation aspects associated closely enough together forming part of broader ecosystem surrounding development efforts targeting next-generation internet technologies aimed squarely addressing challenges faced daily throughout various industries ranging widely including entertainment broadcasting social networking education telemedicine etcetera ad infinitum[^4]. ```python def setup_srs_webrtc(): """ A simplified Python pseudo-code snippet demonstrating basic configuration steps. Note: Actual deployment would require more detailed settings based on specific needs. """ configure_rtmp_input() enable_webrtc_output() start_server() setup_srs_webrtc() ``` --related questions-- 1. What security measures does SRS implement to protect against unauthorized access? 2. How do different codecs impact performance in WebRTC transmissions managed by SRS? 3. Can multiple types of media inputs coexist simultaneously within single instances running SRS v4.0? 4. Are there any limitations regarding geographical locations affecting quality/stability of WebRTC calls served via SRS infrastructure?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值