feat(config): 默认并发调优至 30 并将全套抢购设置置为开箱即用

- 默认并发调优至 30:匹配单实例 30 账号最佳配置,配合 300ms 首发错峰使 30 账号全员在 0~300ms 免排队出击,5 实例多开整机在途约 150
- 前后端默认值与平滑迁移:对齐 Concurrency 30、DelayMS 120、WindowSeconds 30、SID 2203 等,旧配置自动升级
- 测试验证:全套 Go 单元测试通过,前端 Vite 构建成功
This commit is contained in:
yml2213
2026-10-17 18:56:18 +08:00
parent a135effd7a
commit d53306076e
4 changed files with 26 additions and 20 deletions
+8 -9
View File
@@ -61,12 +61,11 @@ const configStorageBase = 'huya-go.gui.config.v2'
const cookieStorageBase = 'huya-go.gui.cookies.v1'
const prizeCacheStorageBase = 'huya-go.gui.prizes.v1'
const leadDefaultMigrationBase = 'huya-go.gui.lead-default.v1'
// 旧版本默认把提前量写成 2500ms、线程写成 5。轮次上限已从产品移除;
// 线程 5 在多开时会放大请求洪峰,旧默认只迁移一次。
// 旧版本默认把提前量写成 2500ms、线程写成 5 或 2。
// 现已调优为单实例 30 账号免排队出击(默认 30 并发)。
const legacyDefaultLeadMs = 2500
const concurrencyDefaultMigrationBase = 'huya-go.gui.concurrency-pressure.v1'
const legacyDefaultConcurrency = 5
const defaultConcurrency = 2
const concurrencyDefaultMigrationBase = 'huya-go.gui.concurrency-v30.v1'
const defaultConcurrency = 30
// 界面本地存储保留的日志上限,与后端的增量拉取配合使用。
const maxClientLogs = 1000
@@ -555,7 +554,7 @@ function readSavedConfig(): Partial<SavedConfig> {
const concurrencyMigrationKey = scopedKey(concurrencyDefaultMigrationBase)
if (!localStorage.getItem(concurrencyMigrationKey)) {
if (Number(saved.concurrency || 0) === legacyDefaultConcurrency) {
if (Number(saved.concurrency || 0) <= 5) {
saved.concurrency = defaultConcurrency
dirty = true
}
@@ -669,7 +668,7 @@ function pickConfig(values: Partial<UiConfig>): UiConfig {
return {
transport: values.transport || 'wss',
wssHost: values.wssHost || '',
sid: Number(values.sid || 0),
sid: Number(values.sid || 2203),
pid: Number(values.pid || 0),
name: values.name || '',
category: values.category || '',
@@ -678,7 +677,7 @@ function pickConfig(values: Partial<UiConfig>): UiConfig {
minLeft: Number(values.minLeft || 0),
cookieText: values.cookieText || '',
selectedAccountLines: values.selectedAccountLines || [],
delayMs: Number(values.delayMs || 150),
delayMs: Number(values.delayMs || 120),
concurrency: Number(values.concurrency || defaultConcurrency),
windowSeconds: Number(values.windowSeconds || 30),
stopAfterSuccess: Boolean(values.stopAfterSuccess),
@@ -2290,7 +2289,7 @@ export default function Dashboard() {
<Form.Item name="delayMs" label="延时">
<InputNumber min={10} max={60000} addonAfter="ms" />
</Form.Item>
<Form.Item name="concurrency" label="线程" tooltip="同时在途请求上限,不是账号槽位;多开时同机总速率约为线程×实例数,限流严重时建议 1~2">
<Form.Item name="concurrency" label="线程" tooltip="同时在途请求上限,默认 30。保证单实例 30 账号在开抢首波 300ms 错峰期间全员免排队出击;5 实例多开整机并发在途约 150">
<InputNumber min={1} max={100} />
</Form.Item>
<Form.Item name="leadMs" label="提前" tooltip="留空或 0 = 按服务端时钟校准误差动态计算(通常几十毫秒);填了就用固定提前量">
+8 -7
View File
@@ -301,11 +301,12 @@ func (a *App) DefaultConfig() Config {
WSSHost: "",
SID: 2203,
DelayMS: 120,
// 线程是「同时在途请求数」,不是账号槽位;多开时同一台机器的总请求速率
// 约为 线程 × 实例数 / 平均 RTT。2026-10-17 的 24 个任务用了旧默认 5,
// 峰值合集约 400~600 请求/秒、84% 被限流,所以默认压到 2,优先换取
// 服务端真正受理请求的概率。账号很多时仍可在界面显式调高。
Concurrency: 2,
// 线程是「同时在途请求数」上限。单机单实例默认 30,
// 5 个多开实例整机约 150 并发(与斗鱼单机 150 吞吐相当)。
// 配合首发 300ms 错峰(10ms 步长),既能确保 30 个账号免排队在
// 0~300ms 黄金期内各打出第 1 枪,又避免瞬间拥堵,兼顾成功率与并发度。
Concurrency: 30,
WindowSeconds: 30,
StopAfterSuccess: false,
StopAccountAfterSuccess: true,
Prewarm: true,
@@ -780,13 +781,13 @@ func normalizeConfig(cfg Config) Config {
}
// WSSHost 留空表示走 launch.queryHttpDns 自动解析,不在这里补默认值。
if cfg.DelayMS <= 0 {
cfg.DelayMS = 150
cfg.DelayMS = 120
}
if cfg.WindowSeconds <= 0 {
cfg.WindowSeconds = sniper.DefaultWindowSeconds
}
if cfg.Concurrency <= 0 {
cfg.Concurrency = 1
cfg.Concurrency = 30
}
if cfg.LeadMS < 0 {
cfg.LeadMS = 0
+8 -2
View File
@@ -73,8 +73,14 @@ func TestDefaultConfigUsesWindowMode(t *testing.T) {
if cfg.LeadMS != 0 {
t.Fatalf("LeadMS=%d, want 0(动态提前量)", cfg.LeadMS)
}
if cfg.Concurrency != 2 {
t.Fatalf("Concurrency=%d, want 2(降低多开时的请求洪峰)", cfg.Concurrency)
if cfg.Concurrency != 30 {
t.Fatalf("Concurrency=%d, want 30(单实例 30 账号全并发首发)", cfg.Concurrency)
}
if cfg.WindowSeconds != 30 {
t.Fatalf("WindowSeconds=%d, want 30", cfg.WindowSeconds)
}
if cfg.DelayMS != 120 {
t.Fatalf("DelayMS=%d, want 120", cfg.DelayMS)
}
if !cfg.Prewarm {
t.Fatal("Prewarm 应默认开启(提前 10 秒异步预热,不阻塞发令枪)")
+2 -2
View File
@@ -13,10 +13,10 @@ func normalizeConfig(cfg Config) Config {
}
// 窗口模式由 deadline 兜底,maxAttempts<=0 表示一直尝试到窗口结束。
if cfg.Delay <= 0 {
cfg.Delay = 150 * time.Millisecond
cfg.Delay = 120 * time.Millisecond
}
if cfg.Concurrency <= 0 {
cfg.Concurrency = 1
cfg.Concurrency = 30
}
if cfg.TooFrequentBackoff <= 0 {
cfg.TooFrequentBackoff = maxDuration(cfg.Delay*2, defaultRetryBackoff)