深入浅出WebRTC—ALR

ALR(Application Limited Region)指的是网络传输过程中,由于应用层的限制(而非网络拥塞)导致带宽未被充分利用的情况。在这种情况下,应用层可能因为处理能力、手动配置或其他因素无法充分利用可用带宽,导致实际传输速率低于网络最大可能提供的速率。因此,在进行拥塞控制或带宽估算时,识别和处理 ALR 状态对于避免不必要的码率下调或误判网络状况至关重要。

1. 配置

ALR逻辑比较简单,配置项就3个,主要用来协助定义进入和退出ALR状态的规则。

struct AlrDetectorConfig {// ALR使用的带宽是估计带宽乘以一个比例系数double bandwidth_usage_ratio = 0.65;// 带宽使用从高点下降,且剩余可用带宽占总容量的比例达到或超过此值时,视为开始进入ALR状态。double start_budget_level_ratio = 0.80;// 当带宽使用回升,且实际使用比例再次超过此值时,认为已从ALR状态中恢复出来。double stop_budget_level_ratio = 0.50;std::unique_ptr<StructParametersParser> Parser();
};

2. 静态结构

ALR实现只有两个类,AlrDetector提供接口,其内部使用IntervalBudget来更新ALR状态,对外接口只有三个:

1)OnBytesSent:每发送完一个报文需要调用此接口,此接口完成Budget水位的更新。

2)SetEstimatedBitrate:设置估计带宽,估计带宽会影响Budget水位调整的细节。

3)GetApplicationLimitedRegionStartTime:如果有值,表示进入ALR状态,否则表示退出ALR状态。这里为什么不用一个bool值来表示是否处于ALR状态,是因为某些逻辑需要知道是什么时候进入ALR状态和什么时候退出ALR状态的。

3. 调用流程

ALR处理逻辑主要涉及两个调用链,一个是发送报文后,调用AlrDetector::OnBytesSent更新Budget水位,通过Budget水位才能判断当前ALR状态;另一个是带宽评估变化调用AlrDetector::SetEstimatedBitrate设置估计带宽,估计带宽会影响水位更新细节和ALR状态判断规则。

4. 实现

4.1. Bucket模型

为了便于理解WebRTC是如何判断ALR状态,引入一个Bucket模型。Bucket中的水位表示当前Budget,可以认为是账户余额,IncreateBudget会向账户中存入资金,增加账户余额,从而提高Bucket中的水位;UseBudget会从账户中支取资金,减少账户余额,从而降低Bucket中的水位。

IntervalBudget是Bucket模型的实现者,只是Budget从金钱换成了数据,每过一段时间 t 计算应该发送的数据:估计带宽 * t,这些数据会存入Budget,每次发送完报文,需要消耗报文对应数据量的Budget。

相关逻辑代码如下:

void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) {...int64_t delta_time_ms = send_time_ms - *last_send_time_ms_;last_send_time_ms_ = send_time_ms;// 减少Budgetalr_budget_.UseBudget(bytes_sent);// 增加Budgetalr_budget_.IncreaseBudget(delta_time_ms);...
}

通过定义桶的高度,并在桶上面画上80%和50%两个刻度,bytes_remaining_为当前Budget水位,从而形成了一个完整的Bucket模型,如下图所示,图中变量与代码中变量一一对应。

其中桶高度max_bytes_in_budget_定义如下:

void IntervalBudget::set_target_rate_kbps(int target_rate_kbps) {// 更新目标速率target_rate_kbps_ = target_rate_kbps;// 计算时间窗口内最多可以发送多少数据,kWindowMs = 500max_bytes_in_budget_ = (kWindowMs * target_rate_kbps_) / 8;...
}

4.2. 估计带宽

从上面的Bucket模型可知,估计带宽会影响到桶的高度和Budget流入的速度。外部会向AlrDectector实时更新估计带宽,但AlrDetector不会全部使用,而是乘以一个系数0.65(这看起来像是一个经验值)再设置到IntervalBudget。

void AlrDetector::SetEstimatedBitrate(int bitrate_bps) {RTC_DCHECK(bitrate_bps);int target_rate_kbps =static_cast<double>(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000;alr_budget_.set_target_rate_kbps(target_rate_kbps);
}

4.3. 水位变化

Bucket中的水位用bytes_remaining_表示,80%和50%两条水位线将桶的水位位置划分为三个区:A、B、C,则水位的变化可以穷举为:A -> B、A -> C、B -> A、B -> C、C -> A、C -> B六种情况。

WebRTC实现定义如果水位处于A区,则一定是“进入ALR”状态,因为实际发送数据远少于应该发送数据;如果水位处于C区,则一定是“退出ALR”状态,因为实际发送数据已经大于应该发送数据。B区是一个过渡区,它的ALR状态和上一个水位相关,下面我们看下水位在A、B和C三个区中动态变化中,ALR状态的变化。

4.3.1. A -> B

刚开始处于“进入ALR”状态,bytes_remaining_比例从高于80%,下降到低于80%但高于50%,ALR状态保持不变。

4.3.2. A -> C

刚开始处于“进入ALR”状态,bytes_remaining_比例从高于80%,下降到低于50%,变为“退出ALR”状态。

4.3.3. B -> A

刚开始可能处于“进入ALR”状态也可能处于“退出ALR”状态,bytes_remaining_从低于80%但高于50%变为高于80%。

1)如果刚开始处于“进入ALR”状态(从A区进入B区),则状态保持不变,仍为“进入ALR”状态;

2)如果刚开始处于“退出ALR”状态(从C区进入B区),则变为“进入ALR”状态。

总之,不管之前是什么状态,进入A区后肯定是“进入ALR”状态。

4.3.4. B -> C

刚开始可能处于“进入ALR”状态也可能处于“退出ALR”状态,bytes_remaining_从低于80%但高于50%变为低于50%。

1)如果刚开始处于“进入ALR”状态(从A区进入B区),则状态变为“退出ALR”状态;

2)如果刚开始处于“退出ALR”状态(从C区进入B区),则状态保持不变,仍为“退出ALR”状态。

总之,不管之前是什么状态,进入C区后肯定是“退出ALR”状态。

4.3.5. C -> A

刚开始处于“退出ALR”状态,bytes_remaining_从低于50%变为高于80%,变为“进入ALR”状态。

4.3.6. C -> B

刚开始处于“退出ALR”状态,bytes_remaining_从低于50%变为高于50%但低于80%,状态保持不变。

4.4. 状态机

以上ALR状态跟随水位变化可以用状态机表示如下:

对应源码为:

void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) {...if (alr_budget_.budget_ratio() > conf_.start_budget_level_ratio && !alr_started_time_ms_) {// 进入ALRalr_started_time_ms_.emplace(rtc::TimeMillis());state_changed = true;} else if (alr_budget_.budget_ratio() < conf_.stop_budget_level_ratio &&alr_started_time_ms_) {// 退出ALRstate_changed = true;alr_started_time_ms_.reset();}...
}

5. ALR应用

5.1. ProbeController

进入ALR状态后,真实发送的码率可能会远低于链路真实容量,如果长时间处于ALR状态而不进行带宽探测,持续的ACK反馈码率会影响最终估计码率,从而导致无法估计带宽失真。因此,专门设置了一个ALR带宽探测机制,进入ALR状态后,ProbeController会立即启动一个ALR带宽探测。

1)GoogCcNetworkController在OnProcessInterval中更新ALR开始时间

NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(ProcessInterval msg) {...// 获取ALR状态absl::optional<int64_t> start_time_ms =alr_detector_->GetApplicationLimitedRegionStartTime();// 设置ALR状态probe_controller_->SetAlrStartTimeMs(start_time_ms);...
}

2)在OnTransportPacketsFeedback中更新ALR结束时间

NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(TransportPacketsFeedback report) {...// 获取ALR状态absl::optional<int64_t> alr_start_time =alr_detector_->GetApplicationLimitedRegionStartTime();// 退出ALR状态if (previously_in_alr_ && !alr_start_time.has_value()) {int64_t now_ms = report.feedback_time.ms();acknowledged_bitrate_estimator_->SetAlrEndedTime(report.feedback_time);probe_controller_->SetAlrEndedTimeMs(now_ms);}...
}

3)ProbeController会定时检测ALR状态,适时启动ALR带宽探测,探测码率是当前评估码率的2倍,带宽探测结果在带宽探测机制中获得。

std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {...// 以两倍估算带宽进行探测:alr_probe_scale("alr_scale", 2)if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {return InitiateProbing(at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);}...
}

5.2. AcknowledgedBitrateEstimator

ACK码率估计器使用贝叶斯估计算法,其中很重要的一个参数就是数据样本的不确定性,应用如果进入ALR状态,则说明此时真实发送的码率低于链路容量,当前ACK样本不能真实反映链路带宽,则应该适当增加当前数据样本的不确定性,使得带宽评估值更加真实可靠。

1)GoogCcNetworkController在OnSentPacket中设置ALR状态

NetworkControlUpdate GoogCcNetworkController::OnSentPacket(SentPacket sent_packet) {alr_detector_->OnBytesSent(sent_packet.size.bytes(), sent_packet.send_time.ms());acknowledged_bitrate_estimator_->SetAlr(alr_detector_->GetApplicationLimitedRegionStartTime().has_value());...
}

2)在OnTransportPacketsFeedback中更新ALR结束时间

NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(TransportPacketsFeedback report) {...// 获取ALR状态absl::optional<int64_t> alr_start_time =alr_detector_->GetApplicationLimitedRegionStartTime();// 退出ALR状态if (previously_in_alr_ && !alr_start_time.has_value()) {int64_t now_ms = report.feedback_time.ms();acknowledged_bitrate_estimator_->SetAlrEndedTime(report.feedback_time);probe_controller_->SetAlrEndedTimeMs(now_ms);}...
}

3)ALR刚结束,码率增速会比正常快,增加贝叶斯估计器历史数据的方差,也就是历史数据的贡献变小,能够更快速响应码率变化。

void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector(const std::vector<PacketResult>& packet_feedback_vector) {...for (const auto& packet : packet_feedback_vector) {// ALR刚结束,设置码率估计器快速响应新的码率if (alr_ended_time_ && packet.sent_packet.send_time > *alr_ended_time_) {bitrate_estimator_->ExpectFastRateChange();alr_ended_time_.reset();}...}
}

4)贝叶斯估计器在更新数据时,如果当前正处于ALR状态,会为数据样本赋予一个更大的不确定性,使得其在整体数据中的贡献占比降低。

void BitrateEstimator::Update(Timestamp at_time, DataSize amount, bool in_alr) {...float scale = uncertainty_scale_;if (is_small_sample && bitrate_sample_kbps < bitrate_estimate_kbps_) {scale = small_sample_uncertainty_scale_;} else if (in_alr && bitrate_sample_kbps < bitrate_estimate_kbps_) {// Optionally use higher uncertainty for samples obtained during ALR.scale = uncertainty_scale_in_alr_;}...
}

5.3. DelayBasedBWE

由于在 ALR 状态下获取的反馈不是链路满载下的反馈,基于这种反馈向上调整带宽估计值很可能是不准确的,因此,ALR 状态保持原来的估计值,是比较明智的。

void AimdRateControl::ChangeBitrate(const RateControlInput& input, Timestamp at_time) {absl::optional<DataRate> new_bitrate;...switch (rate_control_state_) {case RateControlState::kRcHold:break;case RateControlState::kRcIncrease: {// ALR状态不允许升速if (send_side_ && in_alr_ && no_bitrate_increase_in_alr_) {increase_limit = current_bitrate_;}...}...
}

5.4. LossBasedBweV2

基于丢包的带宽估计器,在全局搜索最优带宽和固有丢包率组合时,需要先构造候选带宽。如果当前正处于 ALR 状态,ACK 码率不能反映网络真实带宽,不应该将 ACK 码率作为候选带宽(可配置)。

std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates(bool in_alr) const {...// 添加一个基于 ACK 码率但进行了回退因子调整的候选带宽if (acknowledged_bitrate_.has_value() &&config_->append_acknowledged_rate_candidate) {if (!(config_->not_use_acked_rate_in_alr && in_alr) ||(config_->padding_duration > TimeDelta::Zero() &&last_padding_info_.padding_timestamp + config_->padding_duration >=last_send_time_most_recent_observation_)) {bandwidths.push_back(*acknowledged_bitrate_ *config_->bandwidth_backoff_lower_bound_factor);}}...
}

6. 总结

识别 ALR 状态对 WebRTC 的拥塞控制来说非常重要,很多人可能没有意识到这一点。为什么这么说,是因为,WebRTC 的拥塞控制算法本质上是一种“刀尖上跳舞”的算法,只有当你要求的最大带宽超过链路容量时,才需要做拥塞控制,此时 WebRTC 会在链路容量的上限疯狂试探。如果带宽随便你使用,怎么用都用不完,怎么用都不会造成拥塞,那也就没必要做拥塞控制了。

ALR 状态本质上是用来标识当前带宽是否够用,进入 ALR 状态和退出 ALR 状态,所需要的控制策略是不一样的,相关算法都需要做调整。ALR 状态就像一个全局开关,开和关直接控制着拥塞控制的行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48072.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Authorization Server 自定义 OAuth2 密码模式返回数据结构优化

前言 对接了自定义密码模式&#xff0c;但是返回的数据结构不符合要求 我们需要改成下面格式 开始 我假设你已经对接好了自定义密码功能&#xff0c;不会的话看下面文章 Spring Authorization Server 1.1 扩展实现 OAuth2 密码模式与 Spring Cloud 的整合实战&#xff08;上…

ChatGPT对话:Windows如何将Python训练模型转换为TensorFlow.js格式

【编者按】编者目前正在做手机上的人工智能软件&#xff0c;第一次做这种工作&#xff0c;从一些基本工作开始与ChatGPT交流。对初学者应该有帮助。 一天后修改文章补充内容&#xff1a; 解决TensorFlow 2.X与TensorFlow Decision Forests版本冲突问题&#xff1a; 在使用tens…

像 MvvmLight 一样使用 CommunityToolkit.Mvvm 工具包

文章目录 简介一、安装工具包二、实现步骤1.按照MvvmLight 的结构创建对应文件夹和文件2.编辑 ViewModelLocator3.引用全局资源二、使用详情1.属性2.命令3. 消息通知4. 完整程序代码展示运行结果简介 CommunityToolkit.Mvvm 包(又名 MVVM 工具包,以前称为 Microsoft.Toolkit…

学习计算机

不要只盯着计算机语言学习&#xff0c;你现在已经学习了C语言和Java&#xff0c;暑假又规划学习Python&#xff0c;最后你掌握的就是计算机语言包而已。 2. 建议你找一门想要深挖的语言&#xff0c;沿着这个方向继续往后学习知识就行。计算机语言是学不完的&#xff0c;而未来就…

Programming Studio COSC2803

You must divide the implementation so that each member of the group contributes to every level. iuww520iuww520iuww520iuww520iuww520iuww520iuww520iuww520 Specifically:  Each person must implement one LEVEL 1 (GREEN) sub-task.  Each person must …

[数据集][目标检测]拐杖检测数据集VOC+YOLO格式2778张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2778 标注数量(xml文件个数)&#xff1a;2778 标注数量(txt文件个数)&#xff1a;2778 标注…

【iOS】—— isMemberOfClass isKindOfClass以及源码

【iOS】—— isMemberOfClass & isKindOfClass以及源码 isa指针示例源码解析&#xff1a;isKindOfClass&#xff1a;源码解析&#xff08;实例方法和类方法&#xff09;isMemberOfClass&#xff1a;源码解析&#xff08;实例方法和类方法&#xff09;源码分析总结&#xff…

【中项】系统集成项目管理工程师-第2章 信息技术发展-2.2新一代信息技术及应用-2.2.3大数据与2.2.4区块链

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

@Configuration的proxyBeanMethods

作用&#xff1a;用于控制配置类的代理行为,确定配置类中的 Bean 方法是否被代理&#xff0c;从而影响 Bean 的创建和管理方式 比较 proxyBeanMethods true 默认行为: 当 proxyBeanMethods 设置为 true&#xff08;默认值&#xff09;时&#xff0c;Spring 会为配置类创建一…

HTML进阶:探索语义化标记与可访问性优化

随着Web技术的不断发展&#xff0c;HTML不再仅仅是用来定义网页内容的标记语言&#xff0c;它还被赋予了更多的责任&#xff0c;如提高网页的可读性、可维护性和可访问性。语义化标记&#xff08;Semantic Markup&#xff09;和可访问性优化&#xff08;Accessibility Optimiza…

航班管理系统【C语言版】单文件编写

开发环境 操作系统&#xff1a;Windows 11专业版开发工具&#xff1a;Visual Studio Code编程语言&#xff1a;C 项目考核验收表 1. 设计目标 本项目的目标是设计并实现一个简易的航班管理系统。该系统应具备以下功能&#xff1a; 添加航班信息查询航班信息显示所有航班信…

自动标签的艺术:sklearn中的聚类标签自动分配技术

自动标签的艺术&#xff1a;sklearn中的聚类标签自动分配技术 在机器学习领域&#xff0c;聚类是一种无监督学习方法&#xff0c;它将数据集中的样本分组&#xff0c;使得同一组内的样本相似度高&#xff0c;而不同组之间的样本相似度低。与有监督学习不同&#xff0c;聚类不依…

前端经验:使用sheetjs导出CSV文本为excel

应用场景 很多web表格组件没有提供直接的导出excel功能&#xff0c;但提供了导出CSV的功能。 如果能想办法拿到CSV的内容&#xff0c;就可以利用sheetjs生成excel并导出。 实施步骤 1.拿到CSV的内容字符 每种表格组件都有各自的CSV生成方法&#xff0c;不管用什么方法&…

[python] 利用opencv显示对比试验效果

利用 opencv 显示 对比实验效果 选择有效区域 import os import random import uuidfrom tqdm import tqdm import cv2 import numpy as np import matplotlib.pyplot as plt GT_Dir"results_compare/GT/" Bicubic_dir"results_compare/Bicubic4x/" Phase…

服务器证书基于 OpenSSL一键颁发脚本

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

vue使用了代理跨域,部署上线,使用Nginx配置出现问题,访问不到后端接口

1、如果路由的mode是history模式的要加上框框里的哪句&#xff0c;然后配置下面的location router location / {root /usr/local/app/dist/; #vue文件dist的完整路径try_files $uri $uri/ router;index index.html index.htm;}#error_page 500 502 503 504 /50x.html;lo…

数据分析入门指南:数据库入门(五)

本文将总结CDA认证考试中数据库中部分知识点&#xff0c;内容来源于《CDA模拟题库与备考资料PPT》 。 CDA认证&#xff0c;作为源自中国、面向全球的专业技能认证&#xff0c;覆盖金融、电信、零售、制造、能源、医疗医药、旅游、咨询等多个行业&#xff0c;旨在培养能够胜任数…

RK3328 Debian安装OpenMediaVault

手头有RK3328板卡&#xff0c;自己编译了Debian并烧录跑起来了&#xff0c;拿它来作为NAS使用&#xff0c;在网上找了一些开源的NAS系统&#xff0c;最终敲定使用OpenMediaVault这套&#xff0c;下面是在RK3328 Debian系统下的安装过程&#xff1a; 0、先打开一个Terminal终端…

CVE-2023-33440(任意文件上传)

简介 Faculty Evaluation System v1.0 存在未授权任意文件上传漏洞漏洞 过程 打开靶场 进行目录扫描 发现后台login.php&#xff0c;进入查看 弱口令进行测试&#xff0c;无效&#xff0c;无法进入 根据提示是未授权访问文件上传 &#xff0c;应该是不需要登录就能触发漏洞…

分布式Session共享的5类技术方案,与优劣势比较

分布式Session共享是分布式系统中常见的问题&#xff0c;主要解决在多个服务器之间共享用户会话信息的需求。以下是五种常见的分布式Session共享技术方案及其优劣势比较&#xff1a; 1. Session复制 设计思路&#xff1a; 多个Web服务器之间相互同步Session&#xff0c;每个W…