perf: 运营商账户分发按账户并行,互不等待
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m48s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m48s
分发器每轮原先逐个处理全部运营商账户,每个账户多次 Redis 往返; 测试环境 Redis 走外网,41 个账户一轮约 19 秒,每个账户每 19 秒只领一次, 慢账户拖住其他账户。改为每轮各账户在独立 goroutine 中抢锁并领取, 一轮耗时取决于最慢账户;账户分发锁不变,多实例下同一账户仍只有一个实例领取。 测试环境 worker 的 Redis 连接池由默认 10 调为 100,避免并行分发与轮询执行争抢连接。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,8 @@ services:
|
||||
- JUNHONG_REDIS_PORT=16299
|
||||
- JUNHONG_REDIS_PASSWORD=cpNbWtAaqgo1YJmbMp3h
|
||||
- JUNHONG_REDIS_DB=6
|
||||
# worker 并发轮询与按账户并行分发共用连接池,默认 10 不够
|
||||
- JUNHONG_REDIS_POOL_SIZE=100
|
||||
# JWT 配置(必填)
|
||||
- JUNHONG_JWT_SECRET_KEY=dev-secret-key-for-testing-only-32chars!
|
||||
# 客户端配置(可选,默认 true;false=不强制绑定手机号)
|
||||
|
||||
@@ -137,21 +137,37 @@ func (d *Dispatcher) tick(ctx context.Context, interval time.Duration) {
|
||||
if stopResumeOn {
|
||||
d.dispatchDeviceEvals(ctx, lockTTL)
|
||||
}
|
||||
// 各账户同时分发、互不等待:一轮耗时取决于最慢的账户,而不是全部账户之和。账户分发锁保证同一账户只有一个实例在领。
|
||||
var wg sync.WaitGroup
|
||||
for _, carrier := range carriers {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
break
|
||||
}
|
||||
ok, err := d.store.redis.SetNX(ctx, constants.RedisCarrierDispatchLockKey(carrier.id), d.instanceID, lockTTL).Result()
|
||||
if err != nil || !ok {
|
||||
continue
|
||||
}
|
||||
// 停复机优先:先领取停复机指令占用本秒名额,再领取卡任务。
|
||||
if stopResumeOn {
|
||||
d.dispatchStopResume(ctx, carrier.id)
|
||||
}
|
||||
if cardsReady {
|
||||
d.dispatchCarrier(ctx, carrier)
|
||||
wg.Add(1)
|
||||
go func(carrier carrierEntry) {
|
||||
defer wg.Done()
|
||||
d.dispatchCarrierRound(ctx, carrier, lockTTL, stopResumeOn, cardsReady)
|
||||
}(carrier)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// dispatchCarrierRound 是单个账户的一轮分发:抢账户分发锁,先领停复机指令占用本秒名额,再领卡任务。
|
||||
func (d *Dispatcher) dispatchCarrierRound(ctx context.Context, carrier carrierEntry, lockTTL time.Duration, stopResumeOn, cardsReady bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
d.logger.Error("账户分发 panic,已恢复", zap.Uint("carrier_id", carrier.id), zap.Any("panic", r))
|
||||
}
|
||||
}()
|
||||
ok, err := d.store.redis.SetNX(ctx, constants.RedisCarrierDispatchLockKey(carrier.id), d.instanceID, lockTTL).Result()
|
||||
if err != nil || !ok {
|
||||
return
|
||||
}
|
||||
if stopResumeOn {
|
||||
d.dispatchStopResume(ctx, carrier.id)
|
||||
}
|
||||
if cardsReady {
|
||||
d.dispatchCarrier(ctx, carrier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user