webrtc弱网-AlrDetector类源码分析与算法原理
AlrDetector(应用受限区域检测器)是WebRTC中用于检测发送端是否处于应用层限速状态的核心组件。它通过维护一个基于时间间隔的预算系统,监控实际发送数据量与网络容量之间的关系。当发送速率持续低于网络容量的设定比例(如65%)时,判定进入ALR状态;当发送速率恢复时退出该状态。该检测为拥塞控制算法提供关键状态信号,帮助区分网络拥塞和应用层限速,从而优化带宽估计和速率调整策略。
一、核心功能
AlrDetector
(Application Limited Region Detector)用于检测是否处于应用受限区域(Application Limited Region, ALR)。当应用程序发送数据的速度低于网络容量时,就处于 ALR 状态。该检测器通过监控发送字节数和时间间隔,结合当前估计的带宽,判断是否进入或退出 ALR 状态。
二、核心算法原理
基于预算的比例判断:
使用
IntervalBudget
来模拟一个“发送预算”。预算随时间的推移而增加(按目标带宽比例),随数据发送而减少。
当预算比例超过
start_budget_level_ratio
时,判定进入 ALR;当预算比例低于
stop_budget_level_ratio
时,判定退出 ALR。
带宽使用率控制:
使用
bandwidth_usage_ratio
(默认 0.65)来设定目标发送速率(即估计带宽的 65%),避免过于激进地判断 ALR。
三、关键数据结构
1. AlrDetectorConfig
struct AlrDetectorConfig {double bandwidth_usage_ratio = 0.65; // 带宽使用比例double start_budget_level_ratio = 0.80; // 开始ALR的预算比例阈值double stop_budget_level_ratio = 0.50; // 结束ALR的预算比例阈值std::unique_ptr<StructParametersParser> Parser(); };
2. AlrDetector
类成员
class AlrDetector {private:const AlrDetectorConfig conf_; // 配置参数absl::optional<int64_t> last_send_time_ms_; // 上次发送时间IntervalBudget alr_budget_; // 间隔预算器absl::optional<int64_t> alr_started_time_ms_; // ALR开始时间(若存在则表示处于ALR)RtcEventLog* event_log_; // 事件日志(可选) };
四、核心方法详解
1. 构造函数
AlrDetector::AlrDetector(AlrDetectorConfig config, RtcEventLog* event_log): conf_(config), alr_budget_(0, true), event_log_(event_log) {}
初始化配置和
IntervalBudget
,初始预算为0,启用“可变目标模式”。
2. OnBytesSent
void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) {if (!last_send_time_ms_.has_value()) {last_send_time_ms_ = send_time_ms;return;}int64_t delta_time_ms = send_time_ms - *last_send_time_ms_;last_send_time_ms_ = send_time_ms;alr_budget_.UseBudget(bytes_sent); // 使用预算(发送数据)alr_budget_.IncreaseBudget(delta_time_ms); // 增加预算(随时间)bool state_changed = false;if (alr_budget_.budget_ratio() > conf_.start_budget_level_ratio &&!alr_started_time_ms_) {alr_started_time_ms_.emplace(rtc::TimeMillis()); // 进入ALRstate_changed = true;} else if (alr_budget_.budget_ratio() < conf_.stop_budget_level_ratio &&alr_started_time_ms_) {state_changed = true;alr_started_time_ms_.reset(); // 退出ALR}if (event_log_ && state_changed) {event_log_->Log(std::make_unique<RtcEventAlrState>(alr_started_time_ms_.has_value()));} }
每次发送数据时调用,更新预算并判断ALR状态变化。
记录状态变化事件(如启用了事件日志)。
3. SetEstimatedBitrate
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); }
根据当前估计带宽设置
IntervalBudget
的目标速率(按比例缩放)。
4. GetApplicationLimitedRegionStartTime
absl::optional<int64_t> AlrDetector::GetApplicationLimitedRegionStartTime() const {return alr_started_time_ms_; }
返回当前ALR状态的开始时间(若存在则表示正处于ALR)。
五、设计亮点
灵活配置:支持通过字段试验(Field Trials)动态调整参数,适应不同网络环境和应用场景。
事件日志:可记录ALR状态变化事件,便于后续分析和调试。
预算比例判断:使用相对比例而非绝对值,更具适应性和鲁棒性。
轻量级设计:仅依赖时间戳和字节数,无需复杂计算,适合实时系统。
六、典型工作流程
初始化:构造
AlrDetector
,设置初始带宽(通常为0,后续通过SetEstimatedBitrate
设置)。发送数据:每次发送数据包后调用
OnBytesSent
,更新预算并判断ALR状态。带宽更新:当网络带宽估计更新时,调用
SetEstimatedBitrate
调整目标速率。状态查询:通过
GetApplicationLimitedRegionStartTime
获取当前是否处于ALR及其开始时间。事件记录:若状态变化且启用了事件日志,则记录
RtcEventAlrState
事件。
七、整体流程图
处理发送数据 (OnBytesSent) 流程
检查预算比例并更新ALR状态流程