mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 22:06:38 +08:00
优化
优化
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package cloud115
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ThrottleManager 全局限流/熔断管理器,用于控制 115 API 访问频率与被风控时的全局静默冷却。
|
||||
type ThrottleManager struct {
|
||||
sync.RWMutex
|
||||
isThrottled bool
|
||||
throttleStartTime time.Time
|
||||
throttleNotify chan struct{}
|
||||
throttleDuration time.Duration
|
||||
}
|
||||
|
||||
var (
|
||||
globalThrottleManager *ThrottleManager
|
||||
throttleOnce sync.Once
|
||||
)
|
||||
|
||||
// GetGlobalThrottleManager 获取全局限流管理器单例。
|
||||
func GetGlobalThrottleManager() *ThrottleManager {
|
||||
throttleOnce.Do(func() {
|
||||
globalThrottleManager = NewThrottleManager(60 * time.Second)
|
||||
})
|
||||
return globalThrottleManager
|
||||
}
|
||||
|
||||
// NewThrottleManager 创建限流管理器。
|
||||
func NewThrottleManager(duration time.Duration) *ThrottleManager {
|
||||
if duration <= 0 {
|
||||
duration = 60 * time.Second
|
||||
}
|
||||
return &ThrottleManager{
|
||||
isThrottled: false,
|
||||
throttleNotify: make(chan struct{}),
|
||||
throttleDuration: duration,
|
||||
}
|
||||
}
|
||||
|
||||
// IsThrottled 检查是否处于限流冷却状态。
|
||||
func (tm *ThrottleManager) IsThrottled() bool {
|
||||
tm.RLock()
|
||||
defer tm.RUnlock()
|
||||
|
||||
if !tm.isThrottled {
|
||||
return false
|
||||
}
|
||||
if time.Since(tm.throttleStartTime) >= tm.throttleDuration {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MarkThrottled 标记为限流状态,并启动恢复计时器。
|
||||
func (tm *ThrottleManager) MarkThrottled() {
|
||||
tm.Lock()
|
||||
defer tm.Unlock()
|
||||
|
||||
if tm.isThrottled && time.Since(tm.throttleStartTime) < tm.throttleDuration {
|
||||
return
|
||||
}
|
||||
|
||||
tm.isThrottled = true
|
||||
tm.throttleStartTime = time.Now()
|
||||
|
||||
go tm.startRecoveryTimer()
|
||||
}
|
||||
|
||||
func (tm *ThrottleManager) startRecoveryTimer() {
|
||||
time.Sleep(tm.throttleDuration)
|
||||
|
||||
tm.Lock()
|
||||
defer tm.Unlock()
|
||||
|
||||
tm.isThrottled = false
|
||||
|
||||
select {
|
||||
case tm.throttleNotify <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// WaitThrottleRecovery 如果处于限流状态,挂起等待直到冷却恢复。
|
||||
func (tm *ThrottleManager) WaitThrottleRecovery(ctx context.Context) error {
|
||||
for {
|
||||
if !tm.IsThrottled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(200 * time.Millisecond)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ticker.Stop()
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
ticker.Stop()
|
||||
if !tm.IsThrottled() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset 重置限流状态(主要用于单元测试)。
|
||||
func (tm *ThrottleManager) Reset() {
|
||||
tm.Lock()
|
||||
defer tm.Unlock()
|
||||
tm.isThrottled = false
|
||||
}
|
||||
|
||||
// SetDuration 调整限流冷却时间(用于测试或动态配置)。
|
||||
func (tm *ThrottleManager) SetDuration(d time.Duration) {
|
||||
tm.Lock()
|
||||
defer tm.Unlock()
|
||||
tm.throttleDuration = d
|
||||
}
|
||||
Reference in New Issue
Block a user