面板增加评分系统

┌──────────────────────────────────────────────────┐
│ forward_panel_desktop.py 🖥️ │
│ ┌─────────────────┐ ┌────────────────────┐ │
│ │ 原有故障转移模式 │◄──►│ 🧠 评分调度模式 │ │
│ │ (failover) │切换│ (scoring) │ │
│ │ ✅ 完全保留 │ │ 新增, 可插拔 │ │
│ └─────────────────┘ └────────┬───────────┘ │
│ │ │
│ ┌──────────────▼───────────┐ │
│ │ node_scorer.py 📦 │ │
│ │ NodeScoreScheduler │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ ScoringConfig │ │ │
│ │ │ NodeScore (per-node) │ │ │
│ │ │ NodeState Enum │ │ │
│ │ └─────────────────────┘ │ │
│ └──────────────────────────┘ │
└──────────────────────────────────────────────────┘

— 节点评分主表
CREATE TABLE node_scores (
node_key TEXT PRIMARY KEY, — ‘ip:port’ 唯一标识
name TEXT DEFAULT ”, — 显示名称 (A,B,C…)
ip TEXT NOT NULL,
port INTEGER DEFAULT 0,
score REAL DEFAULT 50.0, — ★ 核心: 0-100实时评分
state TEXT DEFAULT ‘active’, — active/cooldown/blacklist
success_count INTEGER DEFAULT 0, — 累计成功次数
fail_count INTEGER DEFAULT 0, — 累计失败次数
consecutive_successes INTEGER DEFAULT 0, — 连击成功(加分)
consecutive_fails INTEGER DEFAULT 0, — 连击失败(惩罚)
avg_latency_ms REAL DEFAULT 0.0, — EMA平滑平均延迟
last_latency_ms REAL DEFAULT 0.0, — 最近延迟
last_check_time REAL DEFAULT 0.0, — 上次检测时间戳
last_state_change REAL DEFAULT 0.0, — 状态变更时间
cooldown_until REAL DEFAULT 0.0 — 冷却到期时间
);

— 评分历史表(选配,趋势分析)
CREATE TABLE node_score_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
node_key TEXT, score REAL, state TEXT,
event TEXT, — ‘success’ / ‘fail’ / ‘state_change’
latency_ms REAL, recorded_at REAL
);

def _calc_success_adjustment(node, latency_ms) -> float:
“””成功时评分调整”””
adjustment = +5.0 # 基础成功加分

if latency_ms < 50:      adjustment += +3.0  # 极低延迟奖励
elif latency_ms < 100:   adjustment += +1.0  # 低延迟奖励
elif latency_ms >= 200:  adjustment += -2.0  # 高延迟惩罚
elif latency_ms >= 500:  adjustment += -5.0  # 极高延迟惩罚

if node.consecutive_successes > 10:  adjustment += +3.0  # 超长连击
elif node.consecutive_successes > 5: adjustment += +2.0  # 连击奖励

return adjustment

def _calc_failure_adjustment(node) -> float:
“””失败时评分调整”””
adjustment = -15.0 # 基础失败扣分

if node.consecutive_fails >= 3:            # 连续失败阈值
    adjustment += -10.0                    # 额外连败惩罚

return adjustment

最终评分: score = clamp(score + adjustment, 0, 100)

def select_node() -> (node_key, NodeScore):
# 1. 过滤: 排除黑名单节点
eligible = [n for n in nodes if n.state != BLACKLIST]

# 2. 分层: 优先活跃节点, 无活跃时才用冷却节点
candidates = active_nodes if active_nodes else cooldown_nodes

# 3. 权重计算:
#    active:    weight = (score / 100)²
#    cooldown:  weight = (score / 100)² × 0.2
#    blacklist: weight = 0 (被过滤)

# 4. 加权随机选择: random.choices(candidates, weights=weights)
return chosen_node
             score<20          ┌──────────┐
┌────────────────────────────►│ COOLDOWN  │
│                             │ (降权0.2)  │
│                             └─────┬─────┘
│              cooldown过期(60s)     │ score<5
│              + score>30           │
│  ┌──────────┐              ┌──────▼──────┐
└──│  ACTIVE  │◄─────────────│  BLACKLIST  │
   │ (全权)    │  探活成功    │  (排除调度)  │
   └──────────┘  恢复分=30   └──────┬──────┘
        ▲                           │
        │     定时探活(5分钟)        │
        └───────────────────────────┘

┌─────────────────────────────────────────┐
│ ⚙️ 检测设置 │
│ │
│ 检测间隔(秒): [30] 失败阈值(次): [3] │
│ 定时切换(分钟):[0 ] 分钟 (0=关闭) │
│ 流量切换(GB): [0 ] GB (0=关闭) │
│ 黑名单探活(秒):[60] 秒 (10-3600) │
│ │
│ ☑ 🧠 节点智能评分调度 │ ← 勾上这个!
│ 基于评分(0-100)+加权随机替代故障转移 │
│ │
│ [▶ 启动] [⏹ 停止] │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│ 🧠 评分调度 – A | 均分71 活跃3 冷却0 黑名单2 │ ← 根节点汇总
├─────────────────────────────────────────────────────┤
│ ▶ A 🟢88分 │ 10✓/0✗ ⏱42ms ⚖35% │ ← 当前活跃(绿底高亮)
│ B 🔴30分 │ 6✓/4✗ ⏱73ms ⚖9% │ ← 活跃-良好(浅青绿)
│ C 🟡18分 │ 3✓/5✗ ⏱342ms ⚖降权4% 冷却47s │ ← 冷却中(橙底)
│ D 🔴5分 │ 1✓/8✗ ⏱- ⚖排除 │ ← 黑名单(红底)
│ E 🟢95分 │ 10✓/0✗ ⏱49ms ⚖34% │ ← 活跃-优秀(浅青绿)
└─────────────────────────────────────────────────────┘

世界树

一步一步来

您可能还喜欢...