- 新增 docs/seckill-analysis-20261018.md:覆盖 5 台机器 23 实例 562 账号全量指标剖析 - 新增 docs/seckill-optimization-roadmap.md:对标 dygou_go 形成四大工作包优化路线图
7.8 KiB
7.8 KiB
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):若在 1.5 秒内未收到完整响应,立刻以超时错误返回并进入短退避重试,绝不阻塞当前账号的抢购节奏。reqCtx, reqCancel := context.WithTimeout(ctx, cfg.RequestTimeout) exchange, err := client.ScoreExchangePrize(reqCtx, account.UID, account.Cookie, sid, pid) reqCancel()
1.2 剥离「账号未绑定!」分类,彻底解绑会话失效
- 问题根源:
在
internal/sniper/classify.go:116中,把「账号未绑定」归入CategorySessionLost。 10.18 实战中出现 914 次该提示,实证表明:同一账号在遭遇数次「未绑定」后仍能成功抢到并扣分,这纯属虎牙下游和平精英角色服务超时降级。当前代码若连续遇到 8 次会直接永久判死(account.done = true),且界面上频频报警会误导用户。 - 改进设计:
- 引入独立分类
CategoryRoleUnbound = "role_unbound"(角色未绑定 / 服务抖动)。 classifyExchangeText中,「账号未绑定/未绑定账号」映射到CategoryRoleUnbound,真正的凭证失效(「请先登录/登录失效/token失效」)才保留为CategorySessionLost。CategoryRoleUnbound仅触发普通业务重试退避(如 200~300ms),不计入连续会话失效判死阈值(sessionStreak)。- 在
retry.go:179的sessionAliveCategory中补充CategoryTooFrequent,只要服务端返回限流,说明账号凭证依然有效,避免sessionStreak在连续限流中虚假累积。
- 引入独立分类
📦 工作包 2:积分基线与刚性对账体系(借鉴 dygou_go ScoreBaselineStore)
- 业务背景:
抢购高并发下,常有边缘异常:客户端断网、RPC 超时、信封解析异常,但服务端其实已经扣除了积分并将礼包发放至背包。仅凭客户端是否收到
category=success会发生严重漏单! - 改进设计:
- 新增
internal/sniper/score_baseline.go(或internal/score/):- 数据文件:
scores.json(保存在各实例的dataDir下)。 - 记录每个账号的基线积分及时间戳:
{"score": 1250, "at": 1729242000}。
- 数据文件:
- 基线更新时机:
- 用户手动点击「查询积分」时批量更新并落盘。
- 导入/检查 Cookie 时自动更新。
- 刚性对账(Verify / Reconcile):
- 抢购结束后(或用户随时点击「对账核对」):全量异步拉取一次所有账号的最新积分。
- 计算差值:
diff = baseline - current。 - 若
diff == target.Price(或diff > 0),即判定为“刚性扣分成功”,自动将原本标记为超时/未知的单子翻案为“成功”,补齐战报!
- 新增
📦 工作包 3:战报持久化与 Excel / CSV 导出
- 业务背景: 多账号操作、代抢代换必须给客户或管理员提供清晰的明细表格。当前版本任务一结束、窗口一关,明细就消失了,只能通过日志正则翻查,效率极低。
- 改进设计:
- 战报存储:每次抢购开始后,在实例数据目录下维护
last_seckill_report.json。- 字段包含:
AccountUID、TargetPID、TargetName、Price、Status(已抢到/售罄/限流/积分不足等)、Attempts、FirstTime、SuccessTime、Duration、Msg。
- 字段包含:
- 导出功能(在
internal/gui/app.go暴露 Wails 绑定方法):ExportSeckillReportCSV() (string, error)ExportSeckillReportExcel() (string, error)
- 前端界面:
- 在作战表上方或「任务已结束」提示旁增加【导出战报】按钮,一键调出文件保存对话框。
- 战报存储:每次抢购开始后,在实例数据目录下维护
📦 工作包 4:主备目标轮转(Priority Fallback)与售罄自动切换
- 业务背景: 10.18 实战显示,最火爆的怪诞乔克(13433)在 10 秒即彻底售罄,而小黄鸭(13443)和天网(13435)在 15~20 秒依然有充沛库存。目前用户必须人工判断或多开不同实例去分别打。
- 改进设计:
- 支持配置主目标(Priority 1)与备选目标(Priority 2...)。
- 在
runAccountRound调度中:- 默认只对主目标发起
exchangeTarget。 - 一旦主目标在当前实例被全量确认为售罄(
CategorySoldOut),引擎自动标记主目标下线,账号无需停止,后续轮次立即自动无缝打向备选目标,把剩余的 20 秒窗口利用到底!
- 默认只对主目标发起