Files

29 KiB
Raw Permalink Blame History

第六部分:智能调度系统

6.1 实时链路探测

┌──────────────────────────────────────────────────────────────────┐
│                    实时链路探测系统                                │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  探测架构:                                                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                    探测集群                               │    │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐              │    │
│  │  │ 探测节点 │  │ 探测节点 │  │ 探测节点 │  ...         │    │
│  │  │ (北京)   │  │ (上海)   │  │ (广州)   │              │    │
│  │  └────┬─────┘  └────┬─────┘  └────┬─────┘              │    │
│  │       │              │              │                    │    │
│  │       └──────────────┴──────────────┘                    │    │
│  │                      │                                   │    │
│  │               ┌──────┴──────┐                            │    │
│  │               │ 数据汇聚    │                            │    │
│  │               │ (ClickHouse)│                            │    │
│  │               └──────┬──────┘                            │    │
│  │                      │                                   │    │
│  │               ┌──────┴──────┐                            │    │
│  │               │ 分析引擎    │                            │    │
│  │               │ (实时计算)  │                            │    │
│  │               └──────┬──────┘                            │    │
│  │                      │                                   │    │
│  │               ┌──────┴──────┐                            │    │
│  │               │ 调度决策    │                            │    │
│  │               │ (路由更新)  │                            │    │
│  │               └─────────────┘                            │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  探测指标:                                                      │
│  ┌──────────────┬──────────────┬──────────────┬──────────────┐  │
│  │ 指标         │ 方法         │ 频率         │ 精度         │  │
│  ├──────────────┼──────────────┼──────────────┼──────────────┤  │
│  │ Ping         │ ICMP/UDP     │ 每5秒        │ ±1ms         │  │
│  │ Jitter       │ RTT标准差    │ 每5秒        │ ±2ms         │  │
│  │ Loss         │ 统计法       │ 每10秒       │ ±0.1%        │  │
│  │ RTT          │ TCP/UDP      │ 每5秒        │ ±1ms         │  │
│  │ Bandwidth    │ 递增探测     │ 每分钟       │ ±10%         │  │
│  │ Node Load    │ 心跳上报     │ 每10秒       │ ±5%          │  │
│  └──────────────┴──────────────┴──────────────┴──────────────┘  │
│                                                                  │
│  探测数据存储:                                                  │
│  - 实时数据:Redis(最新值,TTL 5分钟)                          │
│  - 历史数据:ClickHouse(聚合后,保留30天)                      │
│  - 告警数据:MySQL(持久化)                                     │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

6.2 调度算法设计

6.2.1 基础版本(规则引擎)

┌──────────────────────────────────────────────────────────────────┐
│                    基础调度算法(规则引擎)                        │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  输入:                                                          │
│  - 用户位置(城市、ISP)                                         │
│  - 游戏服务器位置                                                │
│  - 节点列表及其状态                                              │
│                                                                  │
│  输出:                                                          │
│  - 最优节点                                                      │
│  - 路由路径                                                      │
│                                                                  │
│  规则优先级:                                                    │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  规则1:同城市同ISP → 直连                                │   │
│  │  条件:user.city == node.city && user.isp == node.isp    │   │
│  │  动作:直接选择该节点                                     │   │
│  │  优先级:1(最高)                                        │   │
│  │                                                          │   │
│  │  规则2:同城市跨ISP → BGP节点                             │   │
│  │  条件:user.city == node.city && user.isp != node.isp    │   │
│  │  动作:选择BGP节点                                        │   │
│  │  优先级:2                                                │   │
│  │                                                          │   │
│  │  规则3:同区域跨城市 → 区域核心节点                       │   │
│  │  条件:user.region == node.region && user.city != node.city│  │
│  │  动作:选择区域核心节点                                   │   │
│  │  优先级:3                                                │   │
│  │                                                          │   │
│  │  规则4:跨区域 → 中转节点                                 │   │
│  │  条件:user.region != node.region                         │   │
│  │  动作:选择最优中转节点                                   │   │
│  │  优先级:4                                                │   │
│  │                                                          │   │
│  │  规则5:跨境 → 国际专线节点                               │   │
│  │  条件:user.country != node.country                       │   │
│  │  动作:选择国际专线节点                                   │   │
│  │  优先级:5(最低)                                        │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  伪代码实现:                                                    │
│                                                                  │
│  func basicSchedule(user *User, game *Game) *Node {             │
│      candidates := getCandidateNodes(game)                       │
│                                                                  │
│      // 规则1:同城市同ISP                                       │
│      for _, node := range candidates {                          │
│          if node.City == user.City && node.ISP == user.ISP {   │
│              return node                                        │
│          }                                                      │
│      }                                                          │
│                                                                  │
│      // 规则2:同城市BGP                                         │
│      for _, node := range candidates {                          │
│          if node.City == user.City && node.IsBGP {             │
│              return node                                        │
│          }                                                      │
│      }                                                          │
│                                                                  │
│      // 规则3:同区域核心节点                                     │
│      for _, node := range candidates {                          │
│          if node.Region == user.Region && node.IsCore {        │
│              return node                                        │
│          }                                                      │
│      }                                                          │
│                                                                  │
│      // 规则4:中转节点                                          │
│      bestScore := 0.0                                           │
│      var bestNode *Node                                         │
│      for _, node := range candidates {                          │
│          score := calculateScore(node, user)                    │
│          if score > bestScore {                                 │
│              bestScore = score                                  │
│              bestNode = node                                    │
│          }                                                      │
│      }                                                          │
│      return bestNode                                            │
│  }                                                               │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

6.2.2 高级版本(多因子加权)

┌──────────────────────────────────────────────────────────────────┐
│                    高级调度算法(多因子加权)                      │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  输入因子:                                                      │
│  ┌──────────────┬──────────┬──────────┬──────────────────────┐  │
│  │ 因子         │ 权重     │ 范围     │ 说明                  │  │
│  ├──────────────┼──────────┼──────────┼──────────────────────┤  │
│  │ RTT          │ 0.35     │ 0-500ms  │ 往返延迟              │  │
│  │ Loss Rate    │ 0.25     │ 0-100%   │ 丢包率                │  │
│  │ Jitter       │ 0.15     │ 0-100ms  │ 抖动                  │  │
│  │ Node Load    │ 0.10     │ 0-100%   │ 节点负载              │  │
│  │ ISP Match    │ 0.05     │ 0/1      │ ISP匹配               │  │
│  │ Geo Distance │ 0.05     │ 0-10000km│ 地理距离              │  │
│  │ Line Quality │ 0.05     │ 0-1      │ 线路质量              │  │
│  └──────────────┴──────────┴──────────┴──────────────────────┘  │
│                                                                  │
│  评分公式:                                                      │
│                                                                  │
│  Score(i) = Σ(Wj × normalize(Fij))                             │
│                                                                  │
│  其中:                                                          │
│  - Wj = 第j个因子的权重                                          │
│  - Fij = 节点i在第j个因子上的值                                  │
│  - normalize() = 归一化到[0,1]区间                               │
│                                                                  │
│  归一化方法:                                                    │
│  - RTT: norm = 1 - (RTT / max_RTT)                              │
│  - Loss: norm = 1 - Loss                                        │
│  - Jitter: norm = 1 - (Jitter / max_Jitter)                     │
│  - Load: norm = 1 - Load                                        │
│  - ISP Match: norm = 1 if match else 0                          │
│  - Geo Distance: norm = 1 - (dist / max_dist)                   │
│  - Line Quality: norm = Quality_Score                           │
│                                                                  │
│  伪代码实现:                                                    │
│                                                                  │
│  type ScheduleFactor struct {                                    │
│      Name    string                                             │
│      Weight  float64                                            │
│      MaxVal  float64                                            │
│  }                                                               │
│                                                                  │
│  var factors = []ScheduleFactor{                                │
│      {"rtt", 0.35, 500},                                        │
│      {"loss", 0.25, 1.0},                                       │
│      {"jitter", 0.15, 100},                                     │
│      {"load", 0.10, 1.0},                                       │
│      {"isp_match", 0.05, 1.0},                                  │
│      {"geo_dist", 0.05, 10000},                                 │
│      {"line_quality", 0.05, 1.0},                               │
│  }                                                               │
│                                                                  │
│  func advancedSchedule(user *User, game *Game) *Node {          │
│      candidates := getCandidateNodes(game)                       │
│                                                                  │
│      var bestNode *Node                                         │
│      bestScore := -1.0                                          │
│                                                                  │
│      for _, node := range candidates {                          │
│          score := 0.0                                           │
│                                                                  │
│          // RTT因子                                              │
│          rttNorm := 1.0 - (node.RTT / 500.0)                   │
│          score += 0.35 * rttNorm                                │
│                                                                  │
│          // 丢包因子                                             │
│          lossNorm := 1.0 - node.LossRate                        │
│          score += 0.25 * lossNorm                               │
│                                                                  │
│          // 抖动因子                                             │
│          jitterNorm := 1.0 - (node.Jitter / 100.0)             │
│          score += 0.15 * jitterNorm                             │
│                                                                  │
│          // 负载因子                                             │
│          loadNorm := 1.0 - node.LoadRate                        │
│          score += 0.10 * loadNorm                               │
│                                                                  │
│          // ISP匹配                                              │
│          ispNorm := 0.0                                         │
│          if node.ISP == user.ISP {                              │
│              ispNorm = 1.0                                      │
│          }                                                      │
│          score += 0.05 * ispNorm                                │
│                                                                  │
│          // 地理距离                                             │
│          dist := haversine(user.Lat, user.Lng, node.Lat, node.Lng)│
│          distNorm := 1.0 - (dist / 10000.0)                    │
│          score += 0.05 * distNorm                               │
│                                                                  │
│          // 线路质量                                             │
│          score += 0.05 * node.LineQuality                       │
│                                                                  │
│          if score > bestScore {                                 │
│              bestScore = score                                  │
│              bestNode = node                                    │
│          }                                                      │
│      }                                                          │
│                                                                  │
│      return bestNode                                            │
│  }                                                               │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

6.2.3 AI版本(机器学习)

┌──────────────────────────────────────────────────────────────────┐
│                    AI调度算法(机器学习)                          │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  模型选择:XGBoost / LightGBM                                    │
│  原因:                                                          │
│  - 推理速度快(<1ms)                                            │
│  - 可解释性好                                                    │
│  - 特征重要性可分析                                              │
│  - 训练数据要求相对低                                            │
│                                                                  │
│  特征工程:                                                      │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  用户特征:                                               │   │
│  │  - user_city (one-hot编码)                                │   │
│  │  - user_isp (one-hot编码)                                 │   │
│  │  - user_latency_avg (历史平均延迟)                        │   │
│  │  - user_loss_avg (历史平均丢包率)                         │   │
│  │  - user_bandwidth (用户带宽)                              │   │
│  │  - time_of_day (时段,0-23)                               │   │
│  │  - day_of_week (星期,0-6)                                │   │
│  │  - is_peak_hour (是否高峰时段)                            │   │
│  │                                                          │   │
│  │  节点特征:                                               │   │
│  │  - node_city (one-hot编码)                                │   │
│  │  - node_isp (one-hot编码)                                 │   │
│  │  - node_rtt (当前延迟)                                    │   │
│  │  - node_loss (当前丢包率)                                 │   │
│  │  - node_jitter (当前抖动)                                 │   │
│  │  - node_load (当前负载)                                   │   │
│  │  - node_bandwidth (节点带宽)                              │   │
│  │  - node_line_type (线路类型,0-5)                         │   │
│  │                                                          │   │
│  │  游戏特征:                                               │   │
│  │  - game_id (游戏ID)                                       │   │
│  │  - game_region (游戏区域)                                 │   │
│  │  - game_protocol (游戏协议,TCP/UDP/混合)                 │   │
│  │  - game_server_distance (游戏服务器距离)                  │   │
│  │                                                          │   │
│  │  交叉特征:                                               │   │
│  │  - user_node_distance (用户到节点距离)                    │   │
│  │  - user_node_isp_match (ISP是否匹配)                     │   │
│  │  - node_game_distance (节点到游戏服务器距离)              │   │
│  │  - historical_score (历史评分)                            │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  标签:                                                          │
│  - 实际加速效果评分(0-100)                                     │
│  - 用户满意度(点击"反馈"按钮)                                  │
│  - 是否掉线(0/1)                                               │
│                                                                  │
│  训练流程:                                                      │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                                                          │   │
│  │  ┌──────────┐    ┌──────────┐    ┌──────────┐          │   │
│  │  │ 数据收集 │───→│ 特征工程 │───→│ 模型训练 │          │   │
│  │  │ 30天数据 │    │ 特征提取 │    │ XGBoost  │          │   │
│  │  └──────────┘    └──────────┘    └──────────┘          │   │
│  │       │                                  │              │   │
│  │       │              ┌───────────────────┘              │   │
│  │       │              ↓                                  │   │
│  │       │         ┌──────────┐    ┌──────────┐          │   │
│  │       │         │ 模型评估 │───→│ 模型部署 │          │   │
│  │       │         │ A/B测试  │    │ 在线推理 │          │   │
│  │       │         └──────────┘    └──────────┘          │   │
│  │       │                                                │   │
│  │       └─── 每周重新训练,持续优化                       │   │
│  │                                                          │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  推理流程:                                                      │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                                                          │   │
│  │  func aiSchedule(user *User, game *Game) *Node {        │   │
│  │      candidates := getCandidateNodes(game)               │   │
│  │                                                          │   │
│  │      // 提取特征                                          │   │
│  │      features := extractFeatures(user, candidates, game) │   │
│  │                                                          │   │
│  │      // 模型推理                                          │   │
│  │      scores := model.Predict(features)                   │   │
│  │                                                          │   │
│  │      // 选择最高分节点                                    │   │
│  │      bestIdx := argmax(scores)                           │   │
│  │      return candidates[bestIdx]                          │   │
│  │  }                                                       │   │
│  │                                                          │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  A/B测试:                                                       │
│  - 10%用户使用AI调度                                             │
│  - 90%用户使用高级调度                                           │
│  - 对比指标:延迟、丢包率、用户满意度                            │
│  - 显著提升后全量切换                                            │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘