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()); // 进入ALR
    state_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)。

五、设计亮点

  1. 灵活配置:支持通过字段试验(Field Trials)动态调整参数,适应不同网络环境和应用场景。

  2. 事件日志:可记录ALR状态变化事件,便于后续分析和调试。

  3. 预算比例判断:使用相对比例而非绝对值,更具适应性和鲁棒性。

  4. 轻量级设计:仅依赖时间戳和字节数,无需复杂计算,适合实时系统。


六、典型工作流程

  1. 初始化 :构造 AlrDetector,设置初始带宽(通常为0,后续通过 SetEstimatedBitrate 设置)。

  2. 发送数据 :每次发送数据包后调用 OnBytesSent,更新预算并判断ALR状态。

  3. 带宽更新 :当网络带宽估计更新时,调用 SetEstimatedBitrate 调整目标速率。

  4. 状态查询 :通过 GetApplicationLimitedRegionStartTime 获取当前是否处于ALR及其开始时间。

  5. 事件记录 :若状态变化且启用了事件日志,则记录 RtcEventAlrState 事件。

七、整体流程图

处理发送数据 (OnBytesSent) 流程

检查预算比例并更新ALR状态流程

相关推荐
星恒随风5 分钟前
Linux网络编程:应用层协议究竟是什么?从网络计算器到TCP Socket抽象基类完整实现
linux·网络·笔记·tcp/ip
万联WANFLOW18 分钟前
异地组网速度忽快忽慢到底怎么回事?直连与中继的判断方法和处理步骤
运维·网络·网络协议·p2p
jimmyleeee21 分钟前
Agent安全之六:(ASI06)记忆与上下文投毒——当 AI 把“昨天的错误”当成“今天的真理”
网络·人工智能·安全
SDWAN_Cheap26 分钟前
物理服务器跟云服务器有什么区别,使用于什么场景
运维·服务器
Smoothcloud润云26 分钟前
GPU算力平台推荐:复现实验时,如何判断租用资源是否合适?
服务器·人工智能·深度学习·gpu算力·gpu
Fuyo_111938 分钟前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
辰辰观影1 小时前
字幕导入教程:外挂字幕一键加载方法
网络·经验分享
无糖可乐没有灵魂1 小时前
Golang ❀ Netdiag 一个Go开源的网络排障信息收集工具
网络
jktantan1 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
揽星河..1 小时前
【C语言】猜数字游戏
c语言·算法·游戏