SRS 流媒体服务器集群搭建
单台服务器做直播,总归有单点风险,利用SRS的[Forward机制][1] + [Edge Server][2]设计,可以很容易搭建一个大规模的高可用集群,示意图如下
源站服务器集群:origin server cluster,可以借助forward机制,仅用少量的服务器,专用于处理推流请求。
边缘服务器集群:edge server cluster,可以用N台机器,从源站拉流,用于较大规模的实时播放。
源站前置负载均衡(硬件或软件负载均衡都行),上图中用haproxy来实现tcp的软负载均衡。
边缘服务器前置反向代理(比如:nginx),用于提供统一的播放地址,同时解决跨域问题,给客户端拉流播放。
这样架构的好处有以下:
- 不管是源站集群,还是连缘服务器集群,均可水平扩展,理论上没有上限。
- 源站可以仅用较少的机器,比如2主2从,就能实现一个高可用且性能尚可的集群(如果业务量不大,连slave server都可以省掉)
- 边缘服务器集群,可以根据实际用户量随时调整规模,另外hls切片,可以放在edge server上切片,减轻源站服务器压力。
开始实战,博主2台服务器(centos 7.x),只能在每个虚拟机上用不同的端口启动多个srs实例,模拟master/slave/edge server (注:大家根据实际情况,将下面的ip换成自己真实的ip地址)
- 执行此命令拉取srs源文件
wget http://ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-latest.zip && unzip -q SRS-CentOS6-x86_64-latest.zip
- srs文件夹路径
/mnt/srs/SRS-CentOS6-x86_64-2.0.263
- 进入SRS文件夹内执行命令
sudo bash INSTALL
编译源文件 - srs编译后配置文件路径
/usr/local/srs/conf
- 在conf下新建pm文件夹
mkdir pm
,后面所有自己的集群配置文件都会放入此文件夹
master配置
配置:/usr/local/srs/conf/pm/master.conf
listen 1945;
max_connections 1000;
pid ./objs/pids/srs.master.pid
srs_log_tank file;
srs_log_file ./objs/logs/master/srs.master.log;
http_api {
enabled on;
listen 1995;
}
http_server {
enabled on;
listen 8180;
dir ./objs/nginx/html;
}
stats {
network 0;
disk sda sdb xvda xvdb;
}
vhost __defaultVhost__ {
forward 172.**.***.71:1946 172.**.***.71:1947 172.**.***.73:1946 172.**.***.73:1947;
}
注:最后一段的forward,表示将视频流转发到4台slave服务器
slave配置
配置:/usr/local/srs/conf/pm/slave1.conf、/usr/local/srs/conf/pm/slave2.conf
slave1:
listen 1946;
max_connections 1000;
pid ./objs/pids/srs.slave1.pid
srs_log_tank file;
srs_log_file ./objs/logs/slave/srs.slave1.log;
http_api {
enabled on;
listen 1996;
}
http_server {
enabled on;
listen 8181;
dir ./objs/nginx/html;
}
stats {
network 0;
disk sda sdb xvda xvdb;
}
vhost __defaultVhost__ {
}
slave2:
listen 1947;
max_connections 1000;
pid ./objs/pids/srs.slave2.pid
srs_log_tank file;
srs_log_file ./objs/logs/slave/srs.slave2.log;
http_api {
enabled on;
listen 1997;
}
http_server {
enabled on;
listen 8182;
dir ./objs/nginx/html;
}
stats {
network 0;
disk sda sdb xvda xvdb;
}
vhost __defaultVhost__ {
}
edge配置
配置:/usr/local/srs/conf/pm/edge1.conf、/usr/local/srs/conf/pm/edge2.conf
edge1:
listen 1948;
max_connections 1000;
pid ./objs/pids/srs.edge1.pid
srs_log_tank file;
srs_log_file ./objs/logs/edge/srs.edge1.log;
http_api {
enabled on;
listen 1998;
}
http_server {
enabled on;
listen 8183;
dir ./objs/nginx/html;
}
stats {
network 0;
disk sda sdb xvda xvdb;
}
vhost __defaultVhost__ {
http_remux{
enabled on;
mount [vhost]/[app]/[stream].flv;
hstrs on;
}
hls{
enabled on;
hls_path ./objs/nginx/html;
hls_fragment 3;
hls_window 60;
}
mode remote;
origin 172.**.***.71:1945 172.**.***.71:1946 172.**.***.71:1947 172.**.***.73:1945 172.**.***.73:1946 172.**.***.73:1947;
}
edge2:
listen 1949;
max_connections 1000;
pid ./objs/pids/srs.edge2.pid
srs_log_tank file;
srs_log_file ./objs/logs/edge/srs.edge2.log;
http_api {
enabled on;
listen 1999;
}
http_server {
enabled on;
listen 8184;
dir ./objs/nginx/html;
}
stats {
network 0;
disk sda sdb xvda xvdb;
}
vhost __defaultVhost__ {
http_remux{
enabled on;
mount [vhost]/[app]/[stream].flv;
hstrs on;
}
hls{
enabled on;
hls_path ./objs/nginx/html;
hls_fragment 3;
hls_window 60;
}
mode remote;
origin 172.**.***.71:1945 172.**.***.71:1946 172.**.***.71:1947 172.**.***.73:1945 172.**.***.73:1946 172.**.***.73:1947;
}
注:最后一段的origin 将所有master、slave均做为视频源(origin server),如果播放时,edge发现自己机器上没有数据,会从origin配置的这些源站上去拉视频流。
每台虚拟机上,依次启动:slave1、slave2、master、edge1、edge2
cd /usr/local/srs
sudo ./objs/srs -c ./conf/pm/slave1.conf
sudo ./objs/srs -c ./conf/pm/slave2.conf
sudo ./objs/srs -c ./conf/pm/master.conf
sudo ./objs/srs -c ./conf/pm/edge1.conf
sudo ./objs/srs -c ./conf/pm/edge2.conf
启动成功后,建议先验证下是否工作正常:
-
测试前先打开阿里云安全组上述端口,并打开防火墙端口。
- 阿里云开启安全组端口在此不做说明,具体方法请自行百度。
- linux开启防火墙端口命令
firewall-cmd --zone=public --add-port=1945-1949/tcp --permanent
firewall-cmd --zone=public --add-port=1995-1999/tcp --permanent
firewall-cmd --zone=public --add-port=8180-8184/tcp --permanent
firewall-cmd --reload
-
可以用obs向每个master或slave推流试试,比如
rtmp://47.**.***.38:1945/live/test
或rtmp://101. **.***.215:1945/live/test
,如果推流不报错,说明master/slave工作正常注意:此处使用的是外网ip,而配置中使用的是内网ip通信,务必区分!
-
然后用vlc播放器,验证从slave/edge这些服务器上拉流(比如 rtmp://47.\*\*.\*\*\*.38:1945/live/test 或 rtmp://101.\*\*.\*\*\*.215:1945/live/test,是否播放正常。
srs日志切割
这里说一下日志切割:在
/etc/logrotate.d/
目录下新建如下5个文件:
srs_edge1
:
/usr/local/srs/objs/logs/edge/srs.edge1.log{
copytruncate
daily
rotate 7
missingok
compress
size 16M
}
srs_edge2
:
/usr/local/srs/objs/logs/edge/srs.edge2.log{
copytruncate
daily
rotate 7
missingok
compress
size 16M
}
srs_master
:
/usr/local/srs/objs/logs/master/srs.master.log{
copytruncate
daily
rotate 7
missingok
compress
size 16M
}
srs_slave1
:
/usr/local/srs/objs/logs/slave/srs.slave1.log{
copytruncate
daily
rotate 7
missingok
compress
size 16M
}
srs_slave2
:
/usr/local/srs/objs/logs/slave/srs.slave2.log{
copytruncate
daily
rotate 7
missingok
compress
size 16M
}
之后重启日志切割脚本:/usr/sbin/logrotate /etc/logrotate.conf
haproxy配置启动
如果上述2个步骤均验证ok,接下来就是如何配置haproxy
haproxy可做高性能负载均衡服务器,在其中一台机器上安装haproxy,这里我们使用47.**.***.38
:
-
yum install haproxy (非常简单)
-
vim /etc/haproxy/haproxy.cfg (修改配置文件)
#--------------------------------------------------------------------- # Example configuration for a possible web application. See the # full configuration options online. # # http://haproxy.1wt.eu/download/1.4/doc/configuration.txt # #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode tcp log global option tcplog option dontlognull option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen srs-cluster bind *:1935 mode tcp balance roundrobin server master1 172.**.***.71:1945 server master2 172.**.***.73:1945
注:关键是最后一段,把本机1935端口,转发到后端2台master服务器的1945端口。
sudo systemctl restart haproxy
(重启haproxy)
重启haproxy成功后,可以用obs推流到 rtmp://haproxy\_server\_ip:1935/live/test 试下推流是否正常,如果ok,可以尝试把其中一台master停掉,看看是否有影响。
nginx配置启动
最后是nginx出场了,ngnix的安装类似haproxy,yum install nginx 即可,关键是配置:
- 新建配置文件
nginx_srs.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error\_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream srs {
ip_hash;
server 172.**.***.71:8183;
server 172.**.***.71:8184;
server 172.**.***.73:8183;
server 172.**.***.73:8184;
}
server {
listen 80;
server_name localhost;
location ~ /* {
proxy_pass http://srs;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include servers /*;
}
- nginx启动:
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx_srs.conf
- nginx重启:
/usr/local/nginx/sbin/nginx -s reload
http://nginx\_server\_ip/live/test.m3u8 理论上就能转到后端的edge服务器。注:新增一个upstream用于指定要转发的edge服务器节点,然后在location ~ /* 这里proxy_pass 指定upstream的名字即可(location ~ /* 切记要写在 location / 前面)。这样配置后,访问
后记
发现一个比较严重的bug,nginx无法转发master与slave的流到edge,导致hls的切片无法获取。后续再排查,单独每个edge服务器可以正常工作。
nginx无法分发流的问题可以通过在haproxy配置分发解决,在实际测试中可以流可以得到分发并切片。
博客参考:[开源流媒体服务器SRS学习笔记(4) - Cluster集群方案][3]