news 2026/8/21 6:58:40

mediasoup源码走读(八)——级联

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
mediasoup源码走读(八)——级联

八、级联

8.1、Mediasoup 级联架构

WorkerB
WorkerA
视频流
视频流
视频流
级联
UDP数据包
媒体流
消费者
消费者
消费者
WorkerC
UDP数据包
媒体流
消费者
消费者
消费者
PipeTransportD
PipeTransportC
RouterC
Consumer G
Consumer H
Consumer I
PipeTransportB
RouterB
Consumer D
Consumer E
Consumer F
RouterA
Producer A
Producer B
Producer C
PipeTransportA

级联是媒体流的负载分担

  • WorkerA 处理 Producer A/B/C
  • WorkerB 处理 Consumer D/E/F
  • WorkerC 处理 Consumer G/H/I
  • 每个 Worker 只处理自己负责的媒体流,而非所有媒体流

8.2、级联如何真正实现负载均衡

8.2.1.负载均衡的本质不是"转发",而是"分担"
传统误解真实情况
“级联是将流量从 WorkerA 传到 WorkerB”“级联是将不同的媒体流分配到不同的 Worker”
“WorkerB 负责所有流”“WorkerB 只负责它自己的 Consumer”

示例:1000 人视频会议

  • 单 Worker:需处理 1000 个 Producer + 1000*999 个 Consumer(总流数 ~1M)
  • 2 Worker 级联:
    • WorkerA:处理 500 个 Producer(A1-A500)
    • WorkerB:处理 500 个 Producer(B1-B500)
    • 每个 Worker 仅需处理 500 个 Producer 和 500*999 个 Consumer(总流数 ~500K)
8.2.2.级联工作流程
Client E (WorkerA)Router (WorkerA)PipeTransport (WorkerA)PipeTransport (WorkerB)Router (WorkerB)Producer B (WorkerB)Consumer E (WorkerA)createConsumer(Producer B1)请求级联UDP 请求 Producer B1 流接收请求获取 Producer B1 流发送 RTP 数据包UDP 转发 RTP 数据包接收数据包分发 RTP 数据包播放视频Client E (WorkerA)Router (WorkerA)PipeTransport (WorkerA)PipeTransport (WorkerB)Router (WorkerB)Producer B (WorkerB)Consumer E (WorkerA)

说明

  1. Producer 分配:ClientA 在 WorkerA 上 创建 Producer,ClientB在 WorkerB 创建 Producer

  2. Consumer 分配:ClientC 订阅 WorkerA 的 Producer,ClientD订阅 WorkerB的 Producer, ClientE在 WorkerA 上但他想 订阅 WorkerB 的 Producer

  3. 负载分担:每个 Worker 仅处理自己的 Producer 和 Consumer,不处理其他 Worker 的流

  4. 级联触发

    1)ClientEWorkerA上,想要订阅 Producer B1

    2)Producer B1是在WorkerB上创建的(workerB.createProducer()

    3)WorkerA通过 PipeTransport 向WorkerB请求 Producer B1 的流

    4)WorkerB通过 PipeTransport 将 Producer B1 的流转发给WorkerA

    5)WorkerA将流转发给ClientE

在 WorkerB
在 WorkerA
WokerA上的ClientE 想订阅 Producer B1
Producer B1 所在 Worker?
WorkerA 通过 PipeTransport 请求 WorkerB
直接处理无需级联

8.3、级联配置详解

8.3.1. **Worker 部署规划
PipeTransport
PipeTransport
负载均衡策略
WorkerA: 处理 0-499 流
WorkerB: 处理 500-999 流
WorkerB
WorkerA
8.3.2.配置步骤(Node.js 示例)

(1) WorkerA 配置(处理 0-499 流)

// workerA.js - ClientE 订阅 Producer B1constworkerA=awaitmediasoup.createWorker({...});constrouterA=awaitworkerA.createRouter({...});// 创建 PipeTransport 用于接收 WorkerB 的流constpipeTransportA=awaitworkerA.createPipeTransport({listenIp:{ip:'192.168.1.100',announcedIp:'192.168.1.100'},port:5000});// 创建 Producer (0-499 流)constproducerB=awaitrouterB.produce({track:videoTrack,// 仅处理 0-499 流rtpCapabilities:{...}});

(2)WorkerB 配置(处理 500-999 流)

// workerB.jsconstworkerB=awaitmediasoup.createWorker({...});constrouterB=awaitworkerB.createRouter({...});// 创建 PipeTransport 用于接收 WorkerA 的流constpipeTransportB=awaitworkerB.createPipeTransport({listenIp:{ip:'192.168.1.101',announcedIp:'192.168.1.101'},port:5000});// 创建 Producer (500-999 流)constproducerB=awaitrouterB.produce({track:videoTrack,// 仅处理 500-999 流rtpCapabilities:{...}});

(3) 负载均衡路由配置

// 路由逻辑:当 Client 想订阅 Producer 时,根据 ID 分配 WorkerfunctiongetWorkerForProducer(producerId){constid=parseInt(producerId.split('-')[1]);if(id<500)returnworkerA;elsereturnworkerB;}// 客户端订阅时,如:ClientE 订阅 Producer B1 (ID 为 "producer-501")constconsumerE=awaitrouterA.consume({producerId:"producer-501",// 这是 WorkerB 的 Producertransport:pipeTransportA,// 本 Worker 的 PipeTransportrtpParameters:{type:'pipe'}});

配置关键点

  1. Worker 分配:通过producerId的数值范围决定分配到哪个 Worker
  2. PipeTransport 用途:WorkerA 通过 PipeTransport 向 WorkerB 提供 Producer 流(反之亦然)
  3. 无主从关系:每个 Worker 是平等的,通过路由策略分配负载

8.4、级联与负载均衡的正确关系

1. Mediasoup 负载均衡机制

机制传统负载均衡 (如 Nginx)Mediasoup 级联负载均衡
工作层级七层 (HTTP) / 四层 (TCP)应用层(基于 Producer ID 分配)
负载分配依据IP/端口 / URLProducer ID 范围(应用层逻辑)
实现方式外部负载均衡器内置路由策略(通过 router.pipeToRouter())
负载均衡效果流量均匀分配到服务器媒体流按 Producer 分配到 Worker

2. 为什么级联是真正的负载均衡?

不是数据转发,而是媒体流的路由分担

  1. WorkerA仅处理 Producer 0-499
  2. WorkerB仅处理 Producer 500-999
  3. 当 Client 想订阅 Producer 600 时:
    • Client 通过 WorkerB 的 Router 订阅
    • WorkerB 通过 PipeTransport 向 WorkerA 请求 Producer 600
    • WorkerA 通过 PipeTransport 将 Producer 600 流转发到 WorkerB
  4. 关键点:WorkerB 仅处理自己的 Consumer,不处理 Producer 600 的生成,级联仅在跨 Worker 时触发,仅将需要的这路流转发过来,不增加额外负载

8.5、核心代码走读

1. Producer 分配逻辑(Router.cpp)

文件:worker/src/RTC/Router.cpp

// 根据 Producer ID 分配 WorkerWorker*Router::GetWorkerForProducer(conststd::string&producerId){intid=std::stoi(producerId.substr(producerId.find('-')+1));if(id<500){returnworkerA;// 分配到 WorkerA}else{returnworkerB;// 分配到 WorkerB}}

2. 级联数据转发(PipeTransport.cpp)

文件:worker/src/RTC/PipeTransport.cpp

voidPipeTransport::SendRtpPacket(RTC::RtpPacket*packet){// 1. 检查是否需要级联转发(不是自己 Worker 的 Producer)if(packet->GetProducer()->GetRouter()!=this->router){// 2. 通过 UDP 发送原始 RTP 包到目标 Workerthis->udpSocket->Send(packet->GetData(),packet->GetSize());}else{// 3. 本地处理(不需要级联)this->router->OnRtpPacket(packet);}}

3. Consumer 创建(Router.cpp)

文件:worker/src/RTC/Router.cpp

RTC::Consumer*Router::Consume(conststd::string&consumerId,conststd::string&producerId,constRTC::RtpParameters::Type&type){// 1. 获取 Producer 所在 WorkerWorker*producerWorker=producer->GetRouter()->GetWorker();// 2. 如果 Producer 在其他 Workerif(producerWorker!=this->worker){// 3. 创建 PipeConsumer 用于级联returnnewRTC::PipeConsumer(this,consumerId,producer->GetKind());}else{// 4. 本地处理returnnewRTC::Consumer(this,consumerId,producer->GetKind());}}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 0:44:07

DeepSeek-R1:开源大模型推理革命,6710亿参数如何重塑行业格局

导语 【免费下载链接】DeepSeek-R1 探索新一代推理模型&#xff0c;DeepSeek-R1系列以大规模强化学习为基础&#xff0c;实现自主推理&#xff0c;表现卓越&#xff0c;推理行为强大且独特。开源共享&#xff0c;助力研究社区深入探索LLM推理能力&#xff0c;推动行业发展。【此…

作者头像 李华
网站建设 2026/8/21 11:09:29

毕设分享 垃圾邮件(短信)分类 算法实现

文章目录1 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法1 前言 Hi&#xff0c;大家好&#xff0c;这里是丹成学长&#xff0c;今天做一个nlp项目&#xff0c;基于机器学习的…

作者头像 李华
网站建设 2026/8/22 3:40:31

Spring Cloud Alibaba + Sentinel

在微服务世界里&#xff0c;每个服务就像一个小摊位&#xff0c;生意火爆时&#xff0c;人流汹涌&#xff0c;如果没有保护措施&#xff0c;小摊很容易被“压垮”。这时候&#xff0c;你就需要 Sentinel——微服务界的“护身符”&#xff0c;帮你抵御流量暴击、保护系统稳定运行…

作者头像 李华
网站建设 2026/8/21 19:53:07

一键检测微信网址是否被拦截,附送 PHP/Python/Go 对接源码

分享信息到微信&#xff0c;本是一件再平常不过的事情&#xff0c;但“该内容已被分享到微信”或直接打不开的提示&#xff0c;却像一道无形的墙&#xff0c;阻碍了信息的自由流通。这不仅影响了用户体验&#xff0c;更可能导致推广效果大打折扣。今天&#xff0c;我就来为大家…

作者头像 李华
网站建设 2026/8/21 20:27:53

【重学MySQL】一文搞懂行级锁 无废话版

&#x1f468;‍&#x1f4bb;程序员三明治&#xff1a;个人主页&#x1f525; 个人专栏: 《设计模式精解》 《重学数据结构》&#x1f91e;先做到 再看见&#xff01; 目录行级锁Record LockGap LockNext-Key Lockselect ... for update有啥用&#xff1f;我不加for update不行…

作者头像 李华
网站建设 2026/8/21 21:01:40

7个重塑知识生产力的Obsidian Zettelkasten模板设计策略

7个重塑知识生产力的Obsidian Zettelkasten模板设计策略 【免费下载链接】Obsidian-Templates A repository containing templates and scripts for #Obsidian to support the #Zettelkasten method for note-taking. 项目地址: https://gitcode.com/gh_mirrors/ob/Obsidian-…

作者头像 李华