Clone
1
migrate_v5_CN_nginx for hls
winlin edited this page 2022-07-31 13:16:33 +08:00
This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

HOME > CN > HLS

NGINX for HLS

Note: 如果觉得Github的Wiki访问太慢可以访问 Gitee 镜像。

边缘集群Edge Cluster就是为了解决很多人观看的问题可以支持非常多的人观看直播流。注意

  • SRS Edge只支持直播流协议比如RTMP或HTTP-FLV等参考RTMP Edge Cluster
  • SRS Edge不支持HLS或DASH等切片的直播流本质上它们不是流就是文件分发。
  • SRS Edge不支持WebRTC的流分发这不是Edge设计的目标WebRTC有自己的集群方式参考#2091

本文描述的就是HLS或DASH等切片的边缘集群基于NGINX实现所以也叫NGINX Edge Cluster。

NGINX Edge Cluster

NGINX边缘集群本质上就是带有缓存的反向代理也就是NGNIX Proxy with Cache。

+------------+          +------------+          +------------+          +------------+
+ FFmpeg/OBS +--RTMP-->-+ SRS Origin +--HLS-->--+ NGINX      +--HLS-->--+ Visitors   +
+------------+          +------------+          + Servers    +          +------------+
                                                +------------+          

只需要配置NGINX的缓存策略就可以不需要额外插件NGINX本身就支持

http {
    # For Proxy Cache.
    proxy_cache_path  /tmp/nginx-cache levels=1:2 keys_zone=srs_cache:8m max_size=1000m inactive=600m;
    proxy_temp_path /tmp/nginx-cache/tmp; 

    server {
        listen       8081;
        # For Proxy Cache.
        proxy_cache_valid  404      10s;
        proxy_cache_lock on;
        proxy_cache_lock_age 300s;
        proxy_cache_lock_timeout 300s;
        proxy_cache_min_uses 1;

        location ~ /.+/.*\.(m3u8)$ {
            proxy_pass http://127.0.0.1:8080$request_uri;
            # For Proxy Cache.
            proxy_cache srs_cache;
            proxy_cache_key $scheme$proxy_host$uri$args;
            proxy_cache_valid  200 302  10s;
        }
        location ~ /.+/.*\.(ts)$ {
            proxy_pass http://127.0.0.1:8080$request_uri;
            # For Proxy Cache.
            proxy_cache srs_cache;
            proxy_cache_key $scheme$proxy_host$uri;
            proxy_cache_valid  200 302  60m;
        }
    }
}

Note: 可以配置缓存的目录proxy_cache_pathproxy_temp_path,改成能访问的目录就可以。

Note: 一般不要修改location配置,除非你知道代表什么含义,要改也先跑起来了再改。

一定不能只配置成纯Proxy这样会把负载透传到SRS系统支持的客户端数目还是SRS支持的数目。

开启Cache后无论NGINX多少负载SRS都只有一个流。这样我们可以扩展多个NGINX实现支持非常多的观看并发了。

比如1Mbps的HLS流1000个客户端播放NGINX那么NGINX的带宽就是1Gbps而SRS只有1Mbps。

如果我们扩展10个NGINX每个NGINX是10Gbps带宽那么整个系统的带宽是100Gbps能支持10万并发SRS的带宽消耗只有10Mbps。

如何验证系统正常工作呢这就要用到Benchmark了。

Benchmark

如何压测这个系统呢?可以用srs-bench使用起来非常方便可以用docker直接启动

docker run --rm -it --network=host --name sb ossrs/srs:sb \
  ./objs/sb_hls_load -c 500 \
  -r http://your_server_public_ipv4/live/livestream.m3u8

而且也可以压测RTMP和HTTP-FLV

docker run --rm -it --network=host --name sb ossrs/srs:sb \
  ./objs/sb_http_load -c 500 \
  -r http://your_server_public_ipv4/live/livestream.flv

Note: 每个SB模拟的客户端并发在500到1000个具体以CPU不要超过80%为准,可以启动多个进程压测。

那就让我们动手搞个HLS集群出来吧。

Example

下面我们用docker来构建一个HLS的分发集群。

首先启动SRS源站

./objs/srs -c conf/hls.origin.conf

然后启动NGINX源站

nginx -c $(pwd)/conf/hls.edge.conf

最后,推流到源站:

ffmpeg -re -i doc/source.flv -c copy \
  -f flv rtmp://127.0.0.1/live/livestream

播放HLS

启动压测从NGINX取HLS

docker run --rm -it --network=host --name sb ossrs/srs:sb \
  ./objs/sb_hls_load -c 500 \
  -r http://192.168.0.14:8081/live/livestream.m3u8

可是看到SRS的压力并不大CPU消耗都在NGINX上。

NGINX边缘集群成功解决了HLS的分发问题如果同时需要做低延迟直播分发HTTP-FLV怎么做呢如果要支持HTTPS HLS或者HTTPS-FLV呢

NGINX完全没问题下面就看如何配合SRS Edge Server实现HTTP-FLV和HLS通过NGINX分发。

Work with SRS Edge Server

NGINX边缘集群也可以和SRS Edge Server一起工作可以实现HLS和HTTP-FLV的分发。

+------------+           +------------+
| SRS Origin +--RTMP-->--+ SRS Edge   +
+-----+------+           +----+-------+
      |                       |               +------------+
      |                       +---HTTP-FLV->--+   NGINX    +              +-----------+
      |                                       +   Edge     +--HLS/FLV-->--+ Visitors  +
      +-------HLS--->-------------------------+   Servers  +              +-----------+
                                              +------------+

实现起来很简单只需要在NGINX的服务器上部署一个SRS并让NGINX工作在反向代理模式就可以。

# For SRS streaming, for example:
#   http://r.ossrs.net/live/livestream.flv
location ~ /.+/.*\.(flv)$ {
   proxy_pass http://127.0.0.1:8080$request_uri;
}

这样HLS由NGINX管理缓存和回源而FLV则由SRS Edge缓存和回源。

这个架构虽好实际上NGINX可以直接作为HLS源站这样可以更高性能是否可以呢完全没问题我们看如何完全用NGINX分发HLS。

NGINX Origin Server

由于HLS就是普通的文件因此也可以直接使用NGINX作为HLS源站。

在超高并发的NGINX Edge集群中也可以形成机房级别的小集群从某个NGINX中集中回源这样可以支持更高的并发。

使用NGINX分发HLS文件其实很简单只需要设置root就可以了

  # For HLS delivery
  location ~ /.+/.*\.(m3u8)$ {
    root /usr/local/srs/objs/nginx/html;
    add_header Cache-Control "public, max-age=10";
  }
  location ~ /.+/.*\.(ts)$ {
    root /usr/local/srs/objs/nginx/html;
    add_header Cache-Control "public, max-age=86400";
  }

Note: 这里我们设置了m3u8的缓存时间是10秒需要根据切片的大小调整。

Note: 由于目前SRS支持HLS variant实现HLS的播放统计因此没有NGINX这么高效参考 #2995

Note: SRS应该要设置Cache-Control,因为切片的服务才能动态设置正确的缓存时间,减少延迟,参考 #2991

Debugging

如何判断缓存有没有生效呢可以在NGINX日志中加入一个字段upstream_cache_status分析NGINX日志来判断缓存是否生效

log_format  main  '$upstream_cache_status $remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
access_log  /var/log/nginx/access.log main;

第一个字段就是缓存状态可以用下面的命令分析比如只看TS文件的缓存情况

cat /var/log/nginx/access.log | grep '.ts HTTP' \
  | awk '{print $1}' | sort | uniq -c | sort -r

可以看到哪些是HIT缓存了就不会从SRS下载文件而直接从NGINX获取文件了。

也可以直接在响应头加入这个字段这样可以在浏览器中看每个请求是否HIT了

add_header X-Cache-Status $upstream_cache_status;

Note: 关于缓存生效时间,参考字段proxy_cache_valid的定义,实际上若源站指定了Cache-Control会覆盖这个配置。

aaPanel Configuration

若使用宝塔,那么可以新增一个站点,然后在站点的配置中写入如下配置:

    # For Proxy Cache.
    proxy_cache_path  /tmp/nginx-cache levels=1:2 keys_zone=srs_cache:8m max_size=1000m inactive=600m;
    proxy_temp_path /tmp/nginx-cache/tmp; 

    server {
        listen       80;
        server_name your.domain.com;

        # For Proxy Cache.
        proxy_cache_valid  404      10s;
        proxy_cache_lock on;
        proxy_cache_lock_age 300s;
        proxy_cache_lock_timeout 300s;
        proxy_cache_min_uses 1;

        location ~ /.+/.*\.(m3u8)$ {
            proxy_pass http://127.0.0.1:8080$request_uri;
            # For Proxy Cache.
            proxy_cache srs_cache;
            proxy_cache_key $scheme$proxy_host$uri$args;
            proxy_cache_valid  200 302  10s;
        }
        location ~ /.+/.*\.(ts)$ {
            proxy_pass http://127.0.0.1:8080$request_uri;
            # For Proxy Cache.
            proxy_cache srs_cache;
            proxy_cache_key $scheme$proxy_host$uri;
            proxy_cache_valid  200 302  60m;
        }
    }

注意一般宝塔新增站点侦听的是80端口域名server_name是自己填的域名其他配置同宝塔配置。或者在宝塔的这个站点配置中加入上面的cache和location的配置也可以。