Files
Xboard/.helloagents/archive/2026-04/202604290132_shared-node-traffic-limit/proposal.md
T
yinjianm e847252e12 fix(api): 修复节点流量限额共享统计与父子显隐联动
统一节点流量统计与限额展示口径,节点详情新增昨日流量,
并让今日、昨日和本月使用清晰的半开时间窗口聚合

同 machine_id 或同 host 的节点现在共享当前账期已用流量,
管理端优先使用后端 traffic_limit_snapshot 展示月额度状态,
mi-node 下发的 current_used 也改为共享账期统计

新增 parent_auto_hidden 标记与父节点显隐联动服务,父节点
因自动上线或流量限额变为不可展示时会隐藏当前显示的子节点,
恢复时只恢复这批自动隐藏的子节点,避免覆盖手动操作
2026-04-29 02:24:57 +08:00

8.2 KiB
Raw Blame History

变更提案: shared-node-traffic-limit

元信息

类型: 修复
方案类型: implementation
优先级: P1
状态: 草稿
创建: 2026-04-29

1. 需求

背景

节点管理页的“流量统计”弹层中,“月额度”当前优先使用单个节点的 mi-node metrics 或 v2_server.u + v2_server.d。当同一台机器上配置多个节点时,机器月流量额度是共享的,单节点口径会低估或拆散真实使用量。现有“本月”统计也按自然月聚合,不等同于机器供应商从指定重置日开始的账期。

目标

  • 同一台机器 / 同一 IP 下的多个节点共享月额度使用量。
  • 月额度使用量按当前限额配置的上一个重置边界到现在统计,而不是按自然月或单节点累计。
  • 节点管理页的“月额度 used / limit”、进度条和限额状态使用后端统一快照。
  • 保留“今日 / 昨日 / 本月 / 累计”节点流量统计的现有展示口径,不把自然月统计改成账期统计。

约束条件

时间约束: 
性能约束: 节点列表接口需要避免全表扫描式重复统计,按当前节点集合和共享范围聚合
兼容性约束: 不新增必填数据库字段;未配置 machine_id 的节点仍可按 host/IP 共享
业务约束: 不执行生产数据修复;不改变节点显隐和用户订阅筛选规则

验收标准

  • 同一 machine_id 的两个限额节点,节点管理页显示相同的月额度已用量。
  • 未配置 machine_idhost 相同的两个限额节点,节点管理页显示相同的月额度已用量。
  • 月额度已用量从当前时间之前最近一次重置边界开始统计,例如重置日 18 日则按最近一个 18 日 00:00 起算。
  • 不同 machine_id 或不同 host 的节点不互相累加。
  • 前端在后端缺少共享快照时仍能回退到原有 metrics / u + d 展示。

2. 方案

技术方案

ServerTrafficLimitService 中集中新增共享限额快照能力:

  • 共享范围优先使用 machine_id;未绑定机器时使用规范化后的 host。空 host 回退为单节点范围。
  • 新增当前账期起点计算:根据节点的 traffic_limit_reset_day / traffic_limit_reset_time / traffic_limit_timezone 计算“当前时间之前最近一次重置时间”。
  • 新增共享账期用量统计:从 v2_stat_server 中按共享范围内的 server_id 聚合 record_type='d'u/d,统计窗口为账期起点到当前日。若节点未持久化或没有统计来源,再回退到共享范围内的 u + d
  • buildNodeConfig() 继续返回 mi-node 既有 traffic_limit 结构,但 current_used 改用共享账期用量。
  • 管理端 server/manage/getNodes 为每个节点追加 traffic_limit_snapshot,前端月额度优先使用该快照展示。
  • 管理端 TypeScript 类型和 getNodeTrafficLimitDetail() 同步增加快照优先级,保持缺省兼容。

影响范围

涉及模块:
  - node-traffic-limit: 限额账期、共享范围和当前用量计算
  - admin-frontend: 节点管理页月额度展示数据源
预计变更文件: 5-7 

风险评估

风险 等级 应对
v2_stat_server.record_at 是日粒度,非 00:00 重置时间无法做到小时级切分 按重置日所在自然日作为统计起点,保留 traffic_limit_last_reset_at 和 mi-node metrics 作为运行态辅助;在测试中覆盖 00:00 主路径
同 host 但实际不是同一机器的节点会被共享统计 优先使用 machine_id;未绑定机器时按用户明确要求的同 IP/host 兜底,并在知识库记录规则
前端旧数据结构缺少新快照 前端保留原有 metrics / u + d 回退
改动影响 mi-node 下发的 current_used 仅改变限额模块中的用量口径,不改变配置字段名;用单元测试覆盖共享和非共享场景

方案取舍

唯一方案理由: 共享用量属于限额领域逻辑,集中在 ServerTrafficLimitService 能同时服务节点配置下发和管理端展示,避免前端自行猜测同机节点。
放弃的替代路径:
  - 仅前端按 host 汇总: 只能修展示,无法修正 mi-node 下发的 current_used,且会复制业务规则
  - 新增 machine_quota 表: 能表达机器级额度,但超出本次问题范围,需要新增配置入口和迁移
  - 每次 DNS 解析 host 后按真实 IP 汇总: 接口性能和网络副作用不可控,且域名解析会受环境影响
回滚边界: 可独立回退 ServerTrafficLimitService 的共享快照、ManageController 的 traffic_limit_snapshot 返回和前端快照优先展示;不涉及数据库结构回滚

3. 技术设计

架构设计

flowchart TD
    A[ManageController getNodes] --> B[ServerTrafficLimitService buildSnapshotsForServers]
    C[ServerService buildNodeConfig] --> D[ServerTrafficLimitService buildNodeConfig]
    B --> E[shared scope: machine_id or host]
    D --> E
    E --> F[v2_stat_server cycle usage]
    B --> G[traffic_limit_snapshot]
    G --> H[admin-frontend getNodeTrafficLimitDetail]

API 设计

GET server/manage/getNodes

  • 请求: 保持不变。
  • 响应: 每个节点新增可选字段:
{
  "traffic_limit_snapshot": {
    "enabled": true,
    "limit": 1073741824000,
    "used": 616327110656,
    "percent": 57,
    "suspended": false,
    "status": "normal",
    "cycle_start_at": 1776441600,
    "last_reset_at": 1776441600,
    "next_reset_at": 1779033600,
    "scope_key": "host:82.40.33.225",
    "scope_node_ids": [327, 272]
  }
}

数据模型

不新增数据库字段。共享范围由现有 v2_server.machine_idv2_server.host 推导。


4. 核心场景

场景: 同 IP 节点共享月额度

模块: node-traffic-limit
条件: 两个节点 host 相同,均启用月流量限额,重置日一致。
行为: 管理端打开节点列表并悬停任一节点名称。
结果: 两个节点的“月额度”已用量均为该 host 下节点账期流量合计。

场景: 绑定机器优先共享

模块: node-traffic-limit
条件: 两个节点绑定相同 machine_idhost 可以不同。
行为: 后端生成节点列表或 mi-node 配置。
结果: 共享范围按 machine_id 聚合,不再按 host 分裂。


5. 技术决策

shared-node-traffic-limit#D001: 共享范围优先 machine_id,兜底 host

日期: 2026-04-29
状态: 采纳
背景: 项目已有 v2_server_machinemachine_id,但用户当前问题来自同 IP 多节点共享机器额度,不能要求所有旧节点先补机器绑定。
选项分析:

选项 优点 缺点
A: 只按 machine_id 语义最准确 旧节点或未绑定机器的同 IP 节点无法修复
B: 只按 host/IP 满足截图场景 已绑定机器但 host 不同的同机节点会被拆散
C: machine_id 优先,host 兜底 覆盖新旧两类场景,改动较小 host 相同但非同机的节点会共享统计
决策: 选择方案 C。
理由: 在不新增配置入口的前提下,C 能覆盖已有机器模型和用户明确的同 IP 场景。
影响: ServerTrafficLimitService 成为共享范围规则的唯一实现位置,管理端和节点配置下发共用该规则。

6. 验证策略

verifyMode: test-first
reviewerFocus:
  - app/Services/ServerTrafficLimitService.php 的账期起点、共享范围和回退逻辑
  - app/Http/Controllers/V2/Admin/Server/ManageController.php 的响应兼容性
  - admin-frontend/src/utils/nodes.ts 的快照优先级和旧数据回退
testerFocus:
  - vendor/bin/phpunit tests/Unit/ServerTrafficLimitServiceTest.php
  - vendor/bin/phpunit tests/Unit/Admin/NodeTrafficStatsWindowTest.php
  - php -l app/Services/ServerTrafficLimitService.php
  - php -l app/Http/Controllers/V2/Admin/Server/ManageController.php
uiValidation: optional
riskBoundary:
  - 不执行数据库迁移或生产数据更新
  - 不修改删除节点、重置节点流量等破坏性接口语义

7. 成果设计

N/A。本次不调整节点管理页视觉结构,只修正“月额度”展示数据源。