@@ -30,17 +30,14 @@ type fastSchedulerPosition struct {
3030// 它不在请求热路径内重算全量 score,而是直接复用 Account 上已缓存的
3131// HealthTier / DispatchScore / DynamicConcurrencyLimit。
3232//
33- // 调度策略:两阶段扫描
34- // 1. 优先在验证过的账号(TotalRequests > 10,排在桶前部)中 round-robin
35- // 2. 验证账号全忙时,回退到全量 round-robin
33+ // 调度策略:按健康层级分桶,桶内按调度分排序后 round-robin。
34+ // 验证过的账号只作为同分 tie-breaker,避免历史请求量盖过额度快重置优先级。
3635type FastScheduler struct {
37- mu sync.RWMutex
38- baseLimit int64
39- buckets map [AccountHealthTier ][]fastSchedulerEntry
40- positions map [int64 ]fastSchedulerPosition
41- cursors [3 ]atomic.Uint64
42- provenBounds [3 ]int // 每个 tier 桶中验证过的账号数量(排在前面)
43- provenCurs [3 ]atomic.Uint64 // 验证账号专用 round-robin 游标
36+ mu sync.RWMutex
37+ baseLimit int64
38+ buckets map [AccountHealthTier ][]fastSchedulerEntry
39+ positions map [int64 ]fastSchedulerPosition
40+ cursors [3 ]atomic.Uint64
4441}
4542
4643func NewFastScheduler (baseLimit int64 ) * FastScheduler {
@@ -112,24 +109,22 @@ func (s *FastScheduler) Rebuild(accounts []*Account) {
112109 }
113110
114111 // 每个桶只排序一次 + 重建位置索引 + 计算验证账号边界
115- for tierIdx , tier := range fastSchedulerTierOrder {
112+ for _ , tier := range fastSchedulerTierOrder {
116113 entries := s .buckets [tier ]
117114 if len (entries ) == 0 {
118- s .provenBounds [tierIdx ] = 0
119115 continue
120116 }
121117 sort .SliceStable (entries , func (i , j int ) bool {
122- if entries [i ].proven != entries [j ].proven {
123- return entries [i ].proven
124- }
125118 if entries [i ].dispatchScore == entries [j ].dispatchScore {
119+ if entries [i ].proven != entries [j ].proven {
120+ return entries [i ].proven
121+ }
126122 return entries [i ].dbID < entries [j ].dbID
127123 }
128124 return entries [i ].dispatchScore > entries [j ].dispatchScore
129125 })
130126 s .buckets [tier ] = entries
131127 s .rebuildPositionsLocked (tier )
132- s .provenBounds [tierIdx ] = countProvenEntries (entries )
133128 }
134129}
135130
@@ -172,7 +167,6 @@ func (s *FastScheduler) Acquire() *Account {
172167}
173168
174169// AcquireExcluding 获取下一个可用账号,排除指定的账号 ID 集合
175- // 两阶段调度:优先在验证过的账号中选取,全忙时回退到全量扫描
176170func (s * FastScheduler ) AcquireExcluding (apiKeyID int64 , exclude map [int64 ]bool ) * Account {
177171 return s .AcquireExcludingWithFilter (apiKeyID , exclude , nil )
178172}
@@ -197,20 +191,6 @@ func (s *FastScheduler) AcquireExcludingWithFilter(apiKeyID int64, exclude map[i
197191 continue
198192 }
199193
200- // 阶段 1:优先在验证过的账号(桶前部 provenBound 个)中 round-robin
201- provenBound := s .provenBounds [tierIdx ]
202- if provenBound > 0 {
203- acc , stale := s .scanRangeLocked (tier , 0 , provenBound , & s .provenCurs [tierIdx ], baseLimit , now , apiKeyID , exclude , filter )
204- if acc != nil {
205- return acc
206- }
207- if stale {
208- changed = true
209- break
210- }
211- }
212-
213- // 阶段 2:回退到全量 round-robin
214194 acc , stale := s .scanRangeLocked (tier , 0 , len (bucket ), & s .cursors [tierIdx ], baseLimit , now , apiKeyID , exclude , filter )
215195 if acc != nil {
216196 return acc
@@ -309,23 +289,16 @@ func (s *FastScheduler) insertLocked(acc *Account, now time.Time) {
309289 proven : proven ,
310290 })
311291 sort .SliceStable (entries , func (i , j int ) bool {
312- if entries [i ].proven != entries [j ].proven {
313- return entries [i ].proven
314- }
315292 if entries [i ].dispatchScore == entries [j ].dispatchScore {
293+ if entries [i ].proven != entries [j ].proven {
294+ return entries [i ].proven
295+ }
316296 return entries [i ].dbID < entries [j ].dbID
317297 }
318298 return entries [i ].dispatchScore > entries [j ].dispatchScore
319299 })
320300 s .buckets [tier ] = entries
321301 s .rebuildPositionsLocked (tier )
322- // 更新该 tier 的验证账号边界
323- for tierIdx , t := range fastSchedulerTierOrder {
324- if t == tier {
325- s .provenBounds [tierIdx ] = countProvenEntries (entries )
326- break
327- }
328- }
329302}
330303
331304func (s * FastScheduler ) removeLocked (dbID int64 ) {
@@ -345,23 +318,6 @@ func (s *FastScheduler) removeLocked(dbID int64) {
345318 s .buckets [pos .tier ] = entries
346319 delete (s .positions , dbID )
347320 s .rebuildPositionsLocked (pos .tier )
348- // 更新该 tier 的验证账号边界
349- for tierIdx , t := range fastSchedulerTierOrder {
350- if t == pos .tier {
351- s .provenBounds [tierIdx ] = countProvenEntries (entries )
352- break
353- }
354- }
355- }
356-
357- // countProvenEntries 统计桶中验证过的账号数量(TotalRequests > 10,排在前面)
358- func countProvenEntries (entries []fastSchedulerEntry ) int {
359- for i , e := range entries {
360- if ! e .proven {
361- return i
362- }
363- }
364- return len (entries ) // 全部都是验证过的
365321}
366322
367323func (s * FastScheduler ) rebuildPositionsLocked (tier AccountHealthTier ) {
@@ -377,7 +333,8 @@ func (a *Account) fastSchedulerSnapshot(baseLimit int64, now time.Time) (Account
377333 a .mu .Lock ()
378334 defer a .mu .Unlock ()
379335
380- if isPremium5hPlan (a .PlanType ) && a .UsagePercent5hValid {
336+ if (isPremium5hPlan (a .PlanType ) && a .UsagePercent5hValid ) ||
337+ (IsPlusOrHigherPlan (a .PlanType ) && a .UsagePercent7dValid ) {
381338 a .recomputeSchedulerLocked (baseLimit )
382339 }
383340
0 commit comments