- 新增 docs/seckill-analysis-20261018.md:覆盖 5 台机器 23 实例 562 账号全量指标剖析 - 新增 docs/seckill-optimization-roadmap.md:对标 dygou_go 形成四大工作包优化路线图
95 lines
7.8 KiB
Markdown
95 lines
7.8 KiB
Markdown
# huya-go 全面架构深度分析与优化路线图(对比 dygou_go)
|
||
|
||
> **编制日期**:2026-10-18
|
||
> **基线版本**:huya-go v0.5.3
|
||
> **参考对标**:`/Users/yml/codes/dygou_go`(斗鱼自动化抢购系统)
|
||
> **实战支撑**:2026-10-18 5台机器 23实例 562账号实战日志
|
||
|
||
---
|
||
|
||
## 一、架构与功能全景对比矩阵
|
||
|
||
| 模块 / 维度 | `dygou_go`(斗鱼项目) | `huya-go`(虎牙现状) | 差距与优化潜力等级 |
|
||
|---|---|---|:---:|
|
||
| **1. 兑换请求超时控制** | 细粒度超短超时(秒级超时熔断,区分服务端超时与网络超时),单次请求绝不 hang 住 | 透传全局任务 `ctx`,底层网络超时为 10~15 秒;实战中曾出现账号被 hang 整整 5.07 秒 | 🔴 **高危 / 极高优先级** |
|
||
| **2. 错误分类与退避精度** | 细分 Transient / InFlight / RateLimited / Throttled / StockOut / Terminal;支付有专门退避阶梯 | 「账号未绑定!」被误判为 `CategorySessionLost`;`TooFrequent` 未纳入存活状态;退避阶梯较粗 | 🔴 **高危 / 极高优先级** |
|
||
| **3. 积分基线与刚性扣分对账** | `ScoreBaselineStore`(`scores.json`):抢购前建基线,抢购后自动比对 `余额差值 == 售价`,反查暗中成功单 | 仅抢购成功时单号异步刷新,无基线文件,无全局刚性对账能力,网络闪断或超时导致的暗中成交会漏单 | 🟡 **重要 / 高优先级** |
|
||
| **4. 作战战报持久化与导出** | `last_xiaodian_report.json` 保存战报,支持 GUI 一键导出 Excel / CSV,包含每账号、商品、耗时、状态 | 抢购战果仅保存在内存中,界面关闭或刷新即丢失,无 Excel / CSV 导出功能,代抢对账依赖翻日志 | 🟡 **重要 / 高优先级** |
|
||
| **5. 备选目标多级轮转 (Fallback)** | 允许配置主目标与备选目标,主目标一旦售罄(StockOut),未完成账号自动无缝切换到备选目标 | `RunTargets` 虽支持多目标,但采用同轮平铺探测,无“优先级与售罄自动降级”机制,GUI 仅能填单 PID | 🟡 **重要 / 高优先级** |
|
||
| **6. 成功战报精美长图生成** | 原生 `image/draw` + `freetype` 自动生成战报图片卡片(带标题、成功率、账号列表、耗时),支持一键发群晒单 | 无大图生成功能,用户只能手动截屏或拍照 | 🟢 **体验增强 / 中优先级** |
|
||
| **7. 跨实例同机协同错峰** | 跨平台互斥锁;支持实例级错峰参数,避免同机多开在 0.00s 齐射造成本地网卡与单 IP 限流 | 已做实例数据目录隔离,但同机多实例在 0.00s 同步发射,加剧单 IP 限流(10.18 pc-1 限流比达 60%) | 🟢 **微调优化 / 中优先级** |
|
||
|
||
---
|
||
|
||
## 二、四大优化工作包详细设计
|
||
|
||
### 📦 工作包 1:抢购引擎核心稳态升级(消灭卡死与误杀)
|
||
|
||
#### 1.1 单请求紧凑超时熔断(Per-Request Fast Timeout)
|
||
- **问题根源**:
|
||
在 `internal/sniper/exchange.go` 的 `exchangeTarget` 中,调用 `client.ScoreExchangePrize(ctx, ...)` 时直接透传了外部 `ctx`。底层 WSS/HTTP 连接的超时时间长达 10~15 秒。
|
||
10.18 实战日志证据:账号 `1199664503824` 与 `1199668733274` 在 loop 1 遭遇服务端微服务超时,单次请求足足耗时 **5.07 秒** 才返回 `biz exception:-7`,导致账号在黄金前 5 秒彻底停滞,直接错过抢购。
|
||
- **改进设计**:
|
||
引入秒杀专属请求超时 `RequestTimeout`(建议默认 `1500ms ~ 2000ms`):
|
||
```go
|
||
reqCtx, reqCancel := context.WithTimeout(ctx, cfg.RequestTimeout)
|
||
exchange, err := client.ScoreExchangePrize(reqCtx, account.UID, account.Cookie, sid, pid)
|
||
reqCancel()
|
||
```
|
||
若在 1.5 秒内未收到完整响应,立刻以超时错误返回并进入短退避重试,绝不阻塞当前账号的抢购节奏。
|
||
|
||
#### 1.2 剥离「账号未绑定!」分类,彻底解绑会话失效
|
||
- **问题根源**:
|
||
在 `internal/sniper/classify.go:116` 中,把「账号未绑定」归入 `CategorySessionLost`。
|
||
10.18 实战中出现 914 次该提示,实证表明:同一账号在遭遇数次「未绑定」后仍能成功抢到并扣分,这纯属虎牙下游和平精英角色服务超时降级。当前代码若连续遇到 8 次会直接永久判死(`account.done = true`),且界面上频频报警会误导用户。
|
||
- **改进设计**:
|
||
1. 引入独立分类 `CategoryRoleUnbound = "role_unbound"`(角色未绑定 / 服务抖动)。
|
||
2. `classifyExchangeText` 中,「账号未绑定/未绑定账号」映射到 `CategoryRoleUnbound`,真正的凭证失效(「请先登录/登录失效/token失效」)才保留为 `CategorySessionLost`。
|
||
3. `CategoryRoleUnbound` 仅触发普通业务重试退避(如 200~300ms),不计入连续会话失效判死阈值(`sessionStreak`)。
|
||
4. 在 `retry.go:179` 的 `sessionAliveCategory` 中补充 `CategoryTooFrequent`,只要服务端返回限流,说明账号凭证依然有效,避免 `sessionStreak` 在连续限流中虚假累积。
|
||
|
||
---
|
||
|
||
### 📦 工作包 2:积分基线与刚性对账体系(借鉴 dygou_go ScoreBaselineStore)
|
||
|
||
- **业务背景**:
|
||
抢购高并发下,常有边缘异常:客户端断网、RPC 超时、信封解析异常,但服务端其实已经扣除了积分并将礼包发放至背包。仅凭客户端是否收到 `category=success` 会发生严重漏单!
|
||
- **改进设计**:
|
||
1. 新增 `internal/sniper/score_baseline.go`(或 `internal/score/`):
|
||
- 数据文件:`scores.json`(保存在各实例的 `dataDir` 下)。
|
||
- 记录每个账号的基线积分及时间戳:`{"score": 1250, "at": 1729242000}`。
|
||
2. **基线更新时机**:
|
||
- 用户手动点击「查询积分」时批量更新并落盘。
|
||
- 导入/检查 Cookie 时自动更新。
|
||
3. **刚性对账(Verify / Reconcile)**:
|
||
- 抢购结束后(或用户随时点击「对账核对」):全量异步拉取一次所有账号的最新积分。
|
||
- 计算差值:`diff = baseline - current`。
|
||
- 若 `diff == target.Price`(或 `diff > 0`),即判定为“刚性扣分成功”,自动将原本标记为超时/未知的单子翻案为“成功”,补齐战报!
|
||
|
||
---
|
||
|
||
### 📦 工作包 3:战报持久化与 Excel / CSV 导出
|
||
|
||
- **业务背景**:
|
||
多账号操作、代抢代换必须给客户或管理员提供清晰的明细表格。当前版本任务一结束、窗口一关,明细就消失了,只能通过日志正则翻查,效率极低。
|
||
- **改进设计**:
|
||
1. 战报存储:每次抢购开始后,在实例数据目录下维护 `last_seckill_report.json`。
|
||
- 字段包含:`AccountUID`、`TargetPID`、`TargetName`、`Price`、`Status`(已抢到/售罄/限流/积分不足等)、`Attempts`、`FirstTime`、`SuccessTime`、`Duration`、`Msg`。
|
||
2. 导出功能(在 `internal/gui/app.go` 暴露 Wails 绑定方法):
|
||
- `ExportSeckillReportCSV() (string, error)`
|
||
- `ExportSeckillReportExcel() (string, error)`
|
||
3. 前端界面:
|
||
- 在作战表上方或「任务已结束」提示旁增加【导出战报】按钮,一键调出文件保存对话框。
|
||
|
||
---
|
||
|
||
### 📦 工作包 4:主备目标轮转(Priority Fallback)与售罄自动切换
|
||
|
||
- **业务背景**:
|
||
10.18 实战显示,最火爆的怪诞乔克(13433)在 10 秒即彻底售罄,而小黄鸭(13443)和天网(13435)在 15~20 秒依然有充沛库存。目前用户必须人工判断或多开不同实例去分别打。
|
||
- **改进设计**:
|
||
1. 支持配置主目标(Priority 1)与备选目标(Priority 2...)。
|
||
2. 在 `runAccountRound` 调度中:
|
||
- 默认只对主目标发起 `exchangeTarget`。
|
||
- 一旦主目标在当前实例被全量确认为售罄(`CategorySoldOut`),引擎自动标记主目标下线,账号无需停止,后续轮次立即自动无缝打向备选目标,把剩余的 20 秒窗口利用到底!
|