mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-08 22:24:15 +00:00
43 lines
2.3 KiB
Markdown
43 lines
2.3 KiB
Markdown
|
|
Task Record: Resolve shared-mode traffic flush blocked by stale inboundId=0 delta
|
|||
|
|
|
|||
|
|
Date: 2026-04-24
|
|||
|
|
Related Module: web/service/traffic_flush.go, web/web.go, web/job/xray_traffic_job.go — 流量刷盘
|
|||
|
|
Change Type: Fix
|
|||
|
|
|
|||
|
|
Background
|
|||
|
|
|
|||
|
|
共享模式下流量统计始终为 0,MariaDB 的 `client_traffics` 表从未被写入。排查发现 `traffic-pending.json` 中存在一个残留的 `inboundId: 0` 客户端流量 delta(在 InboundId 解析修复前产生)。`flushToDatabase()` 尝试将其写入 `client_traffics` 时,违反外键约束 `fk_inbounds_client_stats`(`inbounds` 表不存在 `id=0`),导致整个事务回滚,所有流量永远无法写入。
|
|||
|
|
|
|||
|
|
此外,`NewXrayTrafficJob()` 和 `startTrafficFlushLoop()` 各自创建了独立的 `TrafficPendingStore` 实例,指向同一个 `traffic-pending.json` 文件但使用独立的 `sync.Mutex`,存在数据竞争风险。
|
|||
|
|
|
|||
|
|
Changes
|
|||
|
|
|
|||
|
|
- `web/service/traffic_flush.go`:
|
|||
|
|
- `flushToDatabase()` 循环开头新增 `InboundID == 0` 检查,跳过无效 delta 并记录 warning 日志
|
|||
|
|
- `web/job/xray_traffic_job.go`:
|
|||
|
|
- `NewXrayTrafficJob()` 改为接受 `*service.TrafficPendingStore` 参数,不再自行创建 store
|
|||
|
|
- 移除 `config` 包依赖
|
|||
|
|
- `web/web.go`:
|
|||
|
|
- `Server` struct 新增 `trafficStore *service.TrafficPendingStore` 字段
|
|||
|
|
- `Start()` 中统一创建一个 `TrafficPendingStore` 实例
|
|||
|
|
- `startTask()` 和 `startTrafficFlushLoop()` 共享同一个 store 实例,消除双实例竞争
|
|||
|
|
- `web/service/traffic_flush_test.go`:
|
|||
|
|
- 新增 `TestFlushOnceSkipsZeroInboundIdDelta` 测试
|
|||
|
|
|
|||
|
|
Impact
|
|||
|
|
|
|||
|
|
- `web/service/traffic_flush.go`: flushToDatabase() 跳过无效 delta
|
|||
|
|
- `web/web.go`: Server 启动流程变更,store 统一创建
|
|||
|
|
- `web/job/xray_traffic_job.go`: 构造函数签名变更
|
|||
|
|
- 修复后需要删除残留的 `traffic-pending.json` 文件才能生效
|
|||
|
|
|
|||
|
|
Verification
|
|||
|
|
|
|||
|
|
- `go test ./web/service/ -run TestTraffic -v` — PASS
|
|||
|
|
- `go test ./web/service/ -run TestFlushOnceSkipsZeroInboundIdDelta -v` — PASS
|
|||
|
|
|
|||
|
|
Risks And Follow-Up
|
|||
|
|
|
|||
|
|
- 部署时必须删除 `/etc/x-ui/traffic-pending.json`,否则残留的 `inboundId: 0` delta 仍会被跳过(不影响功能,但会产生 warning 日志)
|
|||
|
|
- `TrafficPendingStore` 的文件级锁已通过共享实例解决,但如果未来有多个进程访问同一文件,仍需考虑进程级锁
|