MediaMTX 水平扩展实战指南:Read Replicas 与 CDN 架构部署详解
MediaMTX 水平扩展实战指南Read Replicas 与 CDN 架构部署详解【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtxMediaMTX 是一款面向实时音视频的即用型媒体服务器支持 WebRTC、RTSP、RTMP、SRT、HLS、MPEG-TS、RTP 等多协议发布与读取。当读者或推流端数量增长到一定程度后单机带宽往往成为性能瓶颈。本文以 docs/2-features/19-scalability.md 为骨架系统讲解 MediaMTX 实现水平扩展的两大类方案**Read Replicas读取副本**与CDN 加速并结合仓库源码深入解释hlsCDNSecret、hlsVariant、正则代理路径等关键机制。读完本文你将能够独立搭建一套多副本 负载均衡的 MediaMTX 集群并掌握在 AWS 上通过 NLB / ALB / CloudFront 交付全协议流媒体服务的完整流程。为什么需要水平扩展MediaMTX 默认不做转码re-encoding它只是将发布端送入的码流原样转发给所有读者。在不转码的前提下单机实例的瓶颈几乎总是集中在服务器与读者之间的有限带宽上而不是 CPU 或内存。当并发读者或推流端数量很大时性能会因底层硬件基础设施的瓶颈而明显劣化。解决该问题最有效的手段是水平扩展horizontal scalability部署多台相互协调的服务器实例把负载均匀分摊到各台机器上。MediaMTX 官方文档提供了两种主要实现途径Read Replicas读取副本所有协议通用、延迟最低但需要为每个副本配备独立机器成本相对较高CDN 加速仅适用于 HLS 协议但可彻底缓解突发流量与副本机器成本问题。下文先介绍最核心的 Read Replicas 方案。Read Replicas为读者扩容的经典架构Read Replicas 的核心思路是额外创建若干个 MediaMTX 实例作为读取副本专门负责从一台 MediaMTXorigin源实例拉取码流再分发给终端用户用户连接与请求由负载均衡器load balancer均匀分配到各副本上。发布端publishers始终只面向 origin 实例推流。图为 MediaMTX 文档自带的 Read Replicas 架构示意展示 origin 实例、多个副本与读者之间的关系。副本节点的必备配置每个 Read Replica 必须完成以下两件事添加一个或多个代理路径proxy paths指向 MediaMTX origin 实例。MediaMTX 的代理能力在 Proxy requests 中完整描述在paths段内使用正则表达式路径~^(.)$即可把任意路径的请求转发到 origin 对应的同名路径上。如果读者使用 WebRTC 协议读取由于副本上的 UDP/TCP 端口未对外暴露必须清空webrtcLocalUDPAddress和webrtcLocalTCPAddress并通过webrtcICEServers2启用一个 STUN 服务器让服务端与客户端借助UDP 打洞技术建立 peer connection。详见 Solving WebRTC connectivity issues 中对四种建连方式的排序静态 UDP 端口 → 静态 TCP 端口 → STUN 打洞 → TURN 中继。在副本场景下只有 STUN 打洞或 TURN可行因为静态端口无法在负载均衡后保持一一对应。负载均衡器按协议分层的选型原则不同协议对负载均衡器的要求截然不同这是部署中最容易出错的地方读者使用的协议负载均衡器类型原因RTSP、RTMP、SRTLayer 4四层负载均衡器这些是长连接流式协议四层 LB 按会话转发即可HLS、WebRTCLayer 7七层负载均衡器 sticky sessions会话粘滞单个 HLS 或 WebRTC 会话由多个 HTTP 请求组成必须把同一用户的请求固定转发到同一副本否则会话会断其中 RTSP 默认端口为 8554、RTMP 为 1935、SRT 为 8890通常走 UDP、HLS 为 8888、WebRTC 为 8889下文所有配置均以此为准。通用实现Docker Traefik 搭建完整集群以下三步可在一组通用服务器on-premises 或任意云环境上复现完整集群。第 1 步启动 origin 实例在专门承载 MediaMTX origin 的机器上启动实例docker run -d \ --name mediamtx \ --restart always \ --network host \ bluenviron/mediamtx:1origin 使用默认配置即可发布端直接向该实例推流。第 2 步为所有副本机器编写并挂载配置在每台承载 read replica 的机器上创建mediamtx.ymlwebrtcLocalUDPAddress: webrtcICEServers2: - url: stun:stun.l.google.com:19302 paths: ~^(.)$: source: rtsp://dns-of-origin:8554/$G1 sourceOnDemand: yes请把dns-of-origin替换为 origin 机器的 DNS 或 IP。这份配置包含了两个关键技术点正则代理路径路径名~^(.)$是一个正则表达式$G1会被替换为正则第一组捕获的内容因此rtsp://replica:8554/camera1会被转发到rtsp://dns-of-origin:8554/camera1。这一代理机制在源码中的落点是路径配置结构体 internal/conf/path.go 中的Source与SourceOnDemand字段。sourceOnDemand: yes副本只在有读者时才去 origin 拉流无读者时释放连接。这既节省 origin 与副本之间的带宽也避免浪费资源。值得注意的是源码校验 internal/conf/path.go 强制要求凡是正则表达式路径 静态 source的配置必须显式设置sourceOnDemand: true否则启动时会报错——这正是官方示例必须带这一项的原因。随后在该机器上启动 MediaMTXdocker run -d \ --name mediamtx \ --restart always \ --network host \ -v $PWD/mediamtx.yml:/mediamtx.yml \ bluenviron/mediamtx:1第 3 步用 Traefik 搭建负载均衡器在负载均衡器机器上创建静态配置traefik.yml声明需要暴露的入口端口entryPoints: rtsp: address: :8554 rtmp: address: :1935 srt: address: :8890/udp # SRT usually uses UDP hls: address: :8888 webrtc: address: :8889 providers: file: filename: /etc/traefik/dynamic_conf.yml watch: true再创建动态配置dynamic_conf.ymlTraefik 会自动热加载tcp: routers: rtsp-router: rule: HostSNI(*) entryPoints: [rtsp] service: rtsp-service rtmp-router: rule: HostSNI(*) entryPoints: [rtmp] service: rtmp-service services: rtsp-service: loadBalancer: servers: - address: replica-1-ip:8554 - address: replica-2-ip:8554 rtmp-service: loadBalancer: servers: - address: replica-1-ip:1935 - address: replica-2-ip:1935 udp: routers: srt-router: entryPoints: [srt] service: srt-service services: srt-service: loadBalancer: servers: - address: replica-1-ip:8890 - address: replica-2-ip:8890 http: routers: hls-router: rule: PathPrefix(/) entryPoints: [hls] service: hls-service webrtc-router: rule: PathPrefix(/) entryPoints: [webrtc] service: webrtc-service services: hls-service: loadBalancer: sticky: cookie: name: SERVERID servers: - url: http://replica-1-ip:8888 - url: http://replica-2-ip:8888 webrtc-service: loadBalancer: sticky: cookie: name: SERVERID servers: - url: http://replica-1-ip:8889 - url: http://replica-2-ip:8889注意其中三处与协议特性的对应关系这正是前面选型原则的落地RTSP、RTMP 走tcp段四层转发SRT 走udp段四层转发HLS、WebRTC 走http段七层转发并开启了stickycookieSERVERID保证同一用户的多次 HTTP 请求落在同一副本。最后启动 Traefikdocker run -d \ --name traefik \ --restart always \ --network host \ -v $PWD/traefik.yml:/etc/traefik/traefik.yml \ -v $PWD/dynamic_conf.yml:/etc/traefik/dynamic_conf.yml \ traefik:v3.6.14部署完成后读者只需使用负载均衡器机器的 IP 或 DNS即可用任意协议读取流媒体。免负载均衡器的替代方案如果希望完全跳过负载均衡器也可以把多个副本 IP 绑到同一个域名DNS 多值记录读者用该域名读取。这个方案依赖 DNS 提供商对 IP 顺序的随机化、且依赖客户端随机挑选其中一个 IP因此负载分配的均匀性无法保证只适合实验或低负载场景。AWS 实现从安全组到 Auto Scaling 全流程如果部署在 AWS 上官方文档给出了从安全组到自动扩缩容的完整实施步骤。整个过程涉及 5 个协议端口也可按需裁剪。安全组规划三步mediamtx-load-balancer安全组供负载均衡器使用Inbound rules 添加类型All TCPsource0.0.0.0/0类型All UDPsource0.0.0.0/0。mediamtx-read-replicas安全组供副本使用类型SSHsource 填管理员 IP 段类型All TCPsource 选Custom指定mediamtx-load-balancer安全组类型All UDPsource 选Custom指定mediamtx-load-balancer安全组。mediamtx-origin安全组供 origin 使用类型SSHsource 填管理员 IP 段类型Custom TCP端口8554RTSPsource 选mediamtx-read-replicas安全组放行副本拉流类型All UDPsource 选mediamtx-read-replicas安全组类型Custom TCP端口8554RTSPsource 填发布端 IP 段类型All UDPsource 填发布端 IP 段。启动 origin 与副本实例启动 origin EC2 实例选用 Amazon Linux AMI挂载mediamtx-origin安全组在Advanced Details的User data中粘贴#!/bin/bash dnf update -y dnf install -y docker systemctl start docker systemctl enable docker usermod -aG docker ec2-user docker run -d \ --name mediamtx \ --restart always \ --network host \ bluenviron/mediamtx:1为副本创建 Launch template选用 Amazon Linux AMI挂载mediamtx-read-replicas安全组User data中粘贴注意 shell 中$G1需要转义为\$G1防止被展开#!/bin/bash dnf update -y dnf install -y docker systemctl start docker systemctl enable docker usermod -aG docker ec2-user mkdir -p /etc/mediamtx/ tee /etc/mediamtx/mediamtx.yml EOF webrtcLocalUDPAddress: webrtcICEServers2: - url: stun:stun.l.google.com:19302 paths: ~^(.)$: source: rtsp://dns-of-origin:8554/\$G1 sourceOnDemand: yes EOF docker run -d \ --name mediamtx \ --restart always \ --network host \ -v /etc/mediamtx/mediamtx.yml:/mediamtx.yml \ bluenviron/mediamtx:1把dns-of-origin替换为 origin EC2 实例的私有 DNS。目标组、负载均衡器与自动扩缩容创建 5 个 Target groupstarget type 为Instances先不关联任何实例名称Protocol / Port健康检查配置mediamtx-read-replicas-8554TCP / 8554RTSP健康检查协议 TCPmediamtx-read-replicas-1935TCP / 1935RTMP健康检查协议 TCPmediamtx-read-replicas-8890UDP / 8890SRT健康检查协议 TCPAdvanced settings 中健康检查端口 override 为8554mediamtx-read-replicas-8888HTTP / 8888HLS健康检查协议 HTTPSuccess codes 填404mediamtx-read-replicas-8889HTTP / 8889WebRTC健康检查协议 HTTPSuccess codes 填404其中 HLS/WebRTC 的目标组健康检查成功码取404的原因MediaMTX 的 HLS/WebRTC HTTP 服务对不存在的路径默认返回 404这恰好证明服务进程存活而 200 响应依赖具体流存在与否不适合做存活探针。开启粘滞对mediamtx-read-replicas-8888和mediamtx-read-replicas-8889两个目标组在Attributes→Edit→Target selection configuration中打开Turn on stickiness并保存。创建 Network Load Balancer挂载mediamtx-load-balancer安全组定义 3 个 TCP/UDP 监听器TCP 8554RTSP→mediamtx-read-replicas-8554TCP 1935RTMP→mediamtx-read-replicas-1935UDP 8890SRT→mediamtx-read-replicas-8890创建 Application Load Balancer挂载mediamtx-load-balancer安全组定义 2 个 HTTP 监听器HTTP 8888HLS→mediamtx-read-replicas-8888HTTP 8889WebRTC→mediamtx-read-replicas-8889创建 Auto Scaling group选用前述 Launch template。CPU 和内存参数通常不重要因为 MediaMTX 不转码主要瓶颈在带宽在Load balancing中选Attach to an existing load balancer并勾选全部 5 个目标组在Group size的Desired capacity中设置期望实例数即可实现副本随负载自动伸缩。部署完成后用NLB 的 DNS读取 RTSP / RTMP / SRT 流用ALB 的 DNS读取 HLS / WebRTC 流。按需裁剪单协议场景大幅简化上述流程覆盖了全部协议但如果读者只使用单一协议例如只有 WebRTC可以大幅简化只需要开放对应端口如 8889、只创建对应的负载均衡器如 Application Load Balancer、只创建对应的目标组即可满足需求。CDN 方案把 HLS 缓存压力交给边缘节点Read Replicas 延迟最低、协议全兼容但在性能与成本上存在三个短板突发流量只能靠调整副本数量应对而扩缩容既不即时、又依赖自动扩缩策略或人工干预期间可能临时劣化副本增多会使副本 ↔ origin 之间的带宽饱和形成新的瓶颈每个副本都需要一台独立且可能昂贵的机器。CDN 方案则另辟蹊径在 MediaMTX 的 HLS 服务器前面挂一层 CDN让 CDN 负责存储可缓存文件.mp4/.ts分片等并响应用户请求从而把绝大多数请求的压力从服务器上卸掉。其代价是只有 HLS 协议可用LL-HLSLow-Latency HLS的 playlist 无法被缓存总是回源请求因此往往需要禁用 lowLatency 变体从而引入较大延迟MediaMTX 标准的认证机制失效流始终对所有人开放除非 CDN 自身实现认证。hlsCDNSecretCDN 回源的身份凭证为了让 MediaMTX 识别 CDN 的回源请求并放行可缓存文件CDN 必须在每个请求中注入Authorization: Bearer头其值必须与 MediaMTX 配置中的hlsCDNSecret一致。该机制在源码中清晰可见配置项定义于 internal/conf/conf.goHLSVariant与HLSCDNSecret相邻声明校验逻辑要求hlsCDNSecret只能包含普通凭据支持的字符集internal/conf/conf.go启动时由 internal/core/core.go 注入 HLS 服务器真正判断请求是否来自 CDN 的逻辑位于 internal/servers/hls/http_server.goisCDN : (s.cdnSecret ! ctx.Request.Header.Get(Authorization) Bearer s.cdnSecret)。命中后服务器即认为请求来自受信 CDN按可缓存路径处理。因此该 Secret 本质上是CDN 回源专用口令只有带着正确 Bearer 头的请求才会被当作 CDN 回源流量普通用户请求依旧走 MediaMTX 自身的认证/处理流程。仓库内的 internal/servers/hls/server_test.go 中也以CDNSecret: myCDNSecret验证了该交互。通用实现fmp4 变体 CDN 回源在承载 MediaMTX 的机器上创建mediamtx.ymlhlsCDNSecret: XXXXXXXXXX hlsVariant: fmp4 paths: all:把hlsCDNSecret替换为一段保密密钥。强烈建议使用fmp4变体这能避免 playlist 请求总是穿透到服务器让绝大多数流量被 CDN 命中缓存。hlsVariant在源码 internal/conf/hls_variant.go 中定义为三种取值mpegts、fmp4、lowLatency对应 gohlslib 的 MPEG-TS / fMP4 / Low-Latency 三种封装。配置校验 internal/conf/conf.go 还规定lowLatency变体要求hlsSegmentCount至少为 7其余变体至少为 3。paths: all:是允许所有路径的简写配合默认的空配置即表示所有流路径都可被 CDN 回源访问。随后启动 MediaMTXdocker run -d \ --name mediamtx \ --restart always \ --network host \ bluenviron/mediamtx:1把 CDN 配置为以 MediaMTX 机器为 origin并在回源请求中注入hlsCDNSecret到Authorization: Bearer头。AWS 实现ALB CloudFront创建mediamtx-load-balancer安全组供 origin 前的负载均衡器使用Inbound rules 添加类型All TCPsource0.0.0.0/0。创建mediamtx-origin安全组供托管 MediaMTX 的 EC2 使用类型SSHsource 填管理员 IP 段类型Custom TCP端口8554RTSPsource 填发布端 IP 段类型All UDPsource 填发布端 IP 段类型All TCPsource 选mediamtx-load-balancer安全组。创建 EC2 实例挂载mediamtx-origin安全组。登录 EC2 并配置 MediaMTX写入mediamtx.ymlhlsCDNSecret: XXXXXXXXXX hlsVariant: fmp4 paths: all:然后启动sudo dnf update -y sudo dnf install -y docker sudo systemctl start docker sudo systemctl enable docker sudo usermod -aG docker ec2-user sudo docker run \ -d \ --restartalways \ --name mediamtx \ --network host \ -v $PWD/mediamtx.yml:/mediamtx.yml \ bluenviron/mediamtx:1创建 Target groupTarget Type 保持InstanceProtocol 保持HTTPPort 填8888HLSAdvanced health check settings中 Success codes 填404把该目标组关联到 EC2 实例。创建 Application Load Balancer挂载mediamtx-load-balancer安全组HTTP 端口设为8888HLSTarget group 选择上一步创建的目标组。创建 CloudFront 分发指向该负载均衡器HTTP port 填8888HLS。随后在分发页面编辑 origin在Add custom header下点击Add headerHeader nameAuthorizationValueBearer XXXXX把 XXXX 替换为hlsCDNSecret的实际值编辑默认行为behaviorCache policy 选择UseOriginCacheControlHeaders。完成后即可使用 CloudFront 分发的 URL 读取 HLS 流例如https://xxxxxx.cloudfront.net/stream/把xxxxxx.cloudfront.net替换为分发域名stream替换为具体流路径。方案对比与选型建议维度Read ReplicasCDN 方案支持协议全部RTSP/RTMP/SRT/HLS/WebRTC仅 HLS延迟最低LL-HLS 不可缓存需用 fmp4 变体延迟较高突发流量依赖副本扩缩容不即时CDN 天然抗突发回源瓶颈副本增多可能打满 origin↔副本带宽仅 HLS 回源压力小硬件成本每副本一台机器无需额外副本机器认证支持 MediaMTX 标准认证标准认证失效需 CDN 自建认证实际生产中两者可以结合用 Read Replicas 服务 WebRTC/RTSP/RTMP/SRT 等低延迟或私有协议读者同时把 HLS 读者交给 CDN从而在延迟、协议覆盖与成本之间取得平衡。无论选择哪种方案本文给出的配置都经过了官方文档与仓库源码的双重印证可放心作为生产部署的起点。【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考