Files
huya-go/docs/seckill-optimization-roadmap.md
T
yml2213 908ceb0b3b docs(review): 沉淀 10.18 抢购实战复盘与对比优化路线图
- 新增 docs/seckill-analysis-20261018.md:覆盖 5 台机器 23 实例 562 账号全量指标剖析
- 新增 docs/seckill-optimization-roadmap.md:对标 dygou_go 形成四大工作包优化路线图
2026-10-18 21:23:45 +08:00

7.8 KiB
Raw Blame History

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):
    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 秒窗口利用到底!