10-23 三台机器 13 个实例抢同一次 18:00 的精英手册,把当天日志翻完发现 四个问题都指向"请求发得太猛、发得太早、结论分得太粗": - 被限流的账号仍按 100ms 节奏猛打。单实例锁单 950~1650 次(约 20 QPS)时 18~24 个账号被"您点击太快",而锁单仅 148 次的实例 30 个账号一次全中—— 可见"点击太快/活动火爆"是账号级封禁,继续打只会加深封禁。 - 定时器提前约 100ms 触发,想用这点提前量抵消 RTT,结果 148 次请求 被明确拒绝:"不在时间范围内 不能兑换"。它们全部落在斗鱼估算时间 -0.026s ~ +0.172s,也就是活动还没开闸就冲进去了。 - 积分基线写盘用 os.Rename 覆盖旧文件,Windows 上会报 Access is denied, 三机日志里出现 281 次"积分基线写入失败",基线没落盘导致 pc-1 四个实例 0 条核对记录,且基线为 0 时会误报"积分未见减少"。 - "已达本次活动兑换上限"被记成账号级终止失败。这其实是"该账号在本次活动 里已经换到过了",10-23 日志里这些账号紧接着就报了"积分已扣减,兑换确认"。 - 限流改为单账号阶梯降频:新增 throttleBackoff,第 1 次等 1~2s、第 2 次 2~3s、第 3 次 3~4s……上限 5s,区间内随机取值避免同步醒来。throttleStreak 独立计数,非限流的失败会把它归零——只有"连续被限流"才越等越久。 每个账号跑在自己的 goroutine 里,降频只压它自己的下一次尝试, 不占用并发额度、不影响其它账号的节奏。 - 触发时刻改为精确命中:dynamicAdvance 返回 0,不再提前。另加兜底守卫—— 服务端回"不在时间范围内"时该次尝试不计失败、不消耗 attempts/failStreak、 不触发降频,用 50~150ms 快速重试直到活动真正开始。结果集里的 "失败|不在时间范围内…"同步改写成"等待活动开始",避免界面闪红。 - 积分基线改异步写盘:flushCh 队列 + 后台协程串行写,抢购收尾不再等写盘; 新增 Flush 供需要确定落盘的场合。另按 build tag 分平台解决 Windows os.Rename 不能覆盖已有文件的问题(replace_file_unix/windows.go)。 - "已达兑换上限"单列:新增 outcomeLimitReached,结果集写"已抢到|"前缀, 汇总行加"已达兑换上限=N",既不计入失败也不混进"账号终止"。 - 账号不做全局去重:同一账号可以买多个皮肤,不同实例也可以抢不同皮肤。 - 新增测试 throttle_backoff_test.go(12 个用例):降频阶梯递增、单账号级 隔离、非限流失败重置阶梯、兑换上限不计失败且立即收手、精确命中不提前、 活动未开始不触发降频且不记失败、Flush 同步落盘。 - 三个原有测试因降频语义变化需要调整时间尺度:新增 speedUpThrottleBackoff 只压缩阶梯的时间尺度,不改变阶梯结构。
36 lines
1.3 KiB
Go
36 lines
1.3 KiB
Go
package constants
|
|
|
|
import "time"
|
|
|
|
// Version 应用版本号,与 wails.json version 同步。
|
|
const Version = "0.3.8"
|
|
|
|
// BuildTime 构建时间,由编译时 ldflags 注入。
|
|
var BuildTime = "unknown"
|
|
|
|
const (
|
|
BaseURL = "https://www.douyu.com"
|
|
UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"
|
|
DefaultAttempts = 2
|
|
DefaultConcurrency = 150
|
|
ProductCacheTTL = 30 * time.Second
|
|
|
|
DefaultAppDataDirName = "douyu-go"
|
|
DefaultConfigFile = "config.json"
|
|
DefaultAccountFile = "accounts.txt"
|
|
DefaultLogDir = "logs"
|
|
DefaultSuccessDir = "success_images"
|
|
|
|
// LegacyDefault* 是旧版本相对工作目录存储的位置,仅用于首次迁移。
|
|
LegacyDefaultConfigFile = "config.json"
|
|
LegacyDefaultAccountFile = "data/user.txt"
|
|
|
|
// DefaultTimeAPI 服务端时间校准接口。
|
|
// 斗鱼服务器时间与活动无关,统一用精英手册的 storedetail(能稳定返回
|
|
// data.preExchange.currentTime),所有活动共用。
|
|
DefaultTimeAPI = BaseURL + "/wgapi/ordnc/activity/peace/storedetail?manualID=G4KA4Qnz4LDp7&commodityID=20260120QYOOB_bag274&rid=9263298"
|
|
)
|
|
|
|
// CST 中国标准时间 UTC+8。
|
|
var CST = time.FixedZone("CST", 8*3600)
|