如何确保在源集群模式下访问正确的后端M3U8文件
How to ensure access the right backend M3U8 file in origin cluster mode
从SRS how to transmux HLS wiki,我们知道SRS在hls_path中生成相应的M3U8播放列表,这是我的配置文件:
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
hls {
enabled on;
hls_path /data/hls-records;
hls_fragment 10;
hls_window 60;
}
}
在一个SRS服务器的情况下,每个播放HLS流的客户端都访问同一个推送SRS服务器,没关系。但是在原始集群模式下,有很多SRS服务器,每个流都在其中一个。当客户端播放此 HLS 流时,我们无法保护它可以访问正确的源 SRS 服务器(如果不存在,则会导致 404 http 状态代码)。与 RTMP 和 HTTP-FLV 流不同,SRS 使用 coworker by HTTP-API 特性来重定向正确的源 SRS。
为了解决这个问题,我想到了以下两个解决方案:
- 使用专门的后端 HLS 段 SRS 服务器:
不要在原始 SRS 服务器中生成 M3U8,每个流都转发到该 SRS 服务器,所有 M3U8 都在该服务器中生成,所有 HLS 请求都代理到该服务器(使用 nginx)。缺点。此解决方案仅限于一个实例,无扩展能力和单节点风险。
the origin srs.conf forward config like this:
vhost same.vhost.forward.srs.com {
# forward stream to other servers.
forward {
enabled on;
destination 192.168.1.120:1935;
}
}
where 192.168.1.120 is the backend hls segment SRS server.
- 使用云存储,例如NFS/K8S PV/Distributed 文件系统:
将云存储挂载为每个SRS服务器中的本地文件夹,无论SRS服务器中的流,M3U8文件和ts段都传输到同一个大存储中,因此在HLS请求后,http服务器将它们作为静态文件提供。从我的测试来看,如果云存储的写入速度靠谱,是一个很好的解决方案。但是如果网络抖动或者写入速度没有接收速度快,就会阻塞其他协程,导致SRS异常。
The hls_path config like this:
vhost __defaultVhost__ {
hls {
enabled on;
hls_path /shared_storage/hls-records;
hls_fragment 10;
hls_window 60;
}
}
Here 'shared_stoarge' means a nfs/cephfs/pv mount point.
以上方案在我看来并没有从根本上解决访问问题,我期待针对这种情况找到更可靠的产品解决方案?
当你使用 OriginCluster 时,你必须获得大量的流来服务,有很多编码器可以将流发布到你的媒体服务器。解决问题的关键:
- 永远不要使用单个服务器,使用集群来获得弹性能力,因为将来你可能会得到更多的流。所以转发不好,因为你必须配置一组特殊的流来转发,类似于手动哈希算法。
- 除了带宽,磁盘IO也是瓶颈。您肯定需要一个高性能的网络存储集群。但是要小心,千万不要让SRS直接写入存储,它会阻塞SRS协程。
据我所知,最好的解决办法是:
- 使用SRS Origin Cluster,将HLS写入本地磁盘,或者RAM磁盘更好,以确保磁盘IO永远不会阻塞SRS协程(由状态线程网络IO驱动)。
- 使用网络存储集群来存储 HLS 文件,例如像 AWS S3 这样的云存储,或者 NFS/K8S PV/Distributed 文件系统等等。使用nginx或CDN来交付HLS。
现在的问题是:如何将数据从memory/disk移动到网络存储集群?
您必须通过 Python 或 Go 构建服务:
- 使用
on_hls
回调,通知您的服务移动 HLS 文件。
- 使用
on_publish
回调,通知您的服务启动 FFmpeg 将 RTMP 转换为 HLS。
Note that FFmpeg should pull stream from SRS edge, never from origin server directly.
从SRS how to transmux HLS wiki,我们知道SRS在hls_path中生成相应的M3U8播放列表,这是我的配置文件:
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
hls {
enabled on;
hls_path /data/hls-records;
hls_fragment 10;
hls_window 60;
}
}
在一个SRS服务器的情况下,每个播放HLS流的客户端都访问同一个推送SRS服务器,没关系。但是在原始集群模式下,有很多SRS服务器,每个流都在其中一个。当客户端播放此 HLS 流时,我们无法保护它可以访问正确的源 SRS 服务器(如果不存在,则会导致 404 http 状态代码)。与 RTMP 和 HTTP-FLV 流不同,SRS 使用 coworker by HTTP-API 特性来重定向正确的源 SRS。
为了解决这个问题,我想到了以下两个解决方案:
- 使用专门的后端 HLS 段 SRS 服务器:
不要在原始 SRS 服务器中生成 M3U8,每个流都转发到该 SRS 服务器,所有 M3U8 都在该服务器中生成,所有 HLS 请求都代理到该服务器(使用 nginx)。缺点。此解决方案仅限于一个实例,无扩展能力和单节点风险。
the origin srs.conf forward config like this:
vhost same.vhost.forward.srs.com {
# forward stream to other servers.
forward {
enabled on;
destination 192.168.1.120:1935;
}
}
where 192.168.1.120 is the backend hls segment SRS server.
- 使用云存储,例如NFS/K8S PV/Distributed 文件系统:
将云存储挂载为每个SRS服务器中的本地文件夹,无论SRS服务器中的流,M3U8文件和ts段都传输到同一个大存储中,因此在HLS请求后,http服务器将它们作为静态文件提供。从我的测试来看,如果云存储的写入速度靠谱,是一个很好的解决方案。但是如果网络抖动或者写入速度没有接收速度快,就会阻塞其他协程,导致SRS异常。
The hls_path config like this:
vhost __defaultVhost__ {
hls {
enabled on;
hls_path /shared_storage/hls-records;
hls_fragment 10;
hls_window 60;
}
}
Here 'shared_stoarge' means a nfs/cephfs/pv mount point.
以上方案在我看来并没有从根本上解决访问问题,我期待针对这种情况找到更可靠的产品解决方案?
当你使用 OriginCluster 时,你必须获得大量的流来服务,有很多编码器可以将流发布到你的媒体服务器。解决问题的关键:
- 永远不要使用单个服务器,使用集群来获得弹性能力,因为将来你可能会得到更多的流。所以转发不好,因为你必须配置一组特殊的流来转发,类似于手动哈希算法。
- 除了带宽,磁盘IO也是瓶颈。您肯定需要一个高性能的网络存储集群。但是要小心,千万不要让SRS直接写入存储,它会阻塞SRS协程。
据我所知,最好的解决办法是:
- 使用SRS Origin Cluster,将HLS写入本地磁盘,或者RAM磁盘更好,以确保磁盘IO永远不会阻塞SRS协程(由状态线程网络IO驱动)。
- 使用网络存储集群来存储 HLS 文件,例如像 AWS S3 这样的云存储,或者 NFS/K8S PV/Distributed 文件系统等等。使用nginx或CDN来交付HLS。
现在的问题是:如何将数据从memory/disk移动到网络存储集群?
您必须通过 Python 或 Go 构建服务:
- 使用
on_hls
回调,通知您的服务移动 HLS 文件。 - 使用
on_publish
回调,通知您的服务启动 FFmpeg 将 RTMP 转换为 HLS。
Note that FFmpeg should pull stream from SRS edge, never from origin server directly.