Skip to content

Commit ab598db

Browse files
committed
feat: 实现智能Token选择策略系统
- 新增三种Token选择策略:顺序使用、最优使用、均衡使用 - 支持环境变量TOKEN_SELECTION_STRATEGY动态配置策略 - 实现SequentialSelectionStrategy顺序策略(默认) - 实现OptimalSelectionStrategy最优策略 - 实现BalancedSelectionStrategy均衡策略 - 添加策略状态监控和动态切换功能 - 更新CLAUDE.md文档,添加Token选择策略配置说明 技术改进: - 重构TokenManager,集成选择策略模式 - 优化token选择逻辑,提升并发性能 - 增强日志记录,便于调试和监控 - 保持向后兼容性,默认使用顺序策略
1 parent 5de3e62 commit ab598db

File tree

3 files changed

+343
-18
lines changed

3 files changed

+343
-18
lines changed

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ docker-compose up -d # 启动服务
6262
# 复制配置文件
6363
cp .env.example .env
6464

65+
# === Token选择策略配置 ===
66+
# 控制多个token时的使用顺序,支持三种策略:
67+
TOKEN_SELECTION_STRATEGY=sequential # 顺序使用(默认):按配置顺序依次使用token,用完再用下一个
68+
# TOKEN_SELECTION_STRATEGY=optimal # 最优使用:选择可用次数最多的token
69+
# TOKEN_SELECTION_STRATEGY=balanced # 均衡使用:轮询所有可用token
70+
6571
# === Token管理配置(推荐使用JSON格式) ===
6672
# 新的JSON格式配置方式,支持多认证方式和多token。
6773
#

auth/token_manager.go

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@ import (
44
"fmt"
55
"kiro2api/logger"
66
"kiro2api/types"
7+
"os"
8+
"strings"
79
"sync"
810
"time"
911
)
1012

1113
// TokenManager 简化的token管理器
1214
type TokenManager struct {
13-
cache *SimpleTokenCache
14-
configs []AuthConfig
15-
mutex sync.RWMutex
16-
lastRefresh time.Time
15+
cache *SimpleTokenCache
16+
configs []AuthConfig
17+
mutex sync.RWMutex
18+
lastRefresh time.Time
19+
selectionStrategy TokenSelectionStrategy // 新增:token选择策略
20+
configOrder []string // 新增:配置顺序
1721
}
1822

1923
// SimpleTokenCache 简化的token缓存
@@ -42,9 +46,31 @@ func NewSimpleTokenCache(ttl time.Duration) *SimpleTokenCache {
4246

4347
// NewTokenManager 创建新的token管理器
4448
func NewTokenManager(configs []AuthConfig) *TokenManager {
49+
// 确定选择策略类型
50+
strategyType := getTokenSelectionStrategy()
51+
52+
// 生成配置顺序
53+
configOrder := generateConfigOrder(configs)
54+
55+
// 创建选择策略
56+
strategy, err := CreateTokenSelectionStrategy(strategyType, configOrder)
57+
if err != nil {
58+
logger.Warn("创建token选择策略失败,使用默认策略",
59+
logger.Err(err),
60+
logger.String("requested_strategy", string(strategyType)))
61+
strategy = NewOptimalSelectionStrategy()
62+
}
63+
64+
logger.Info("TokenManager初始化",
65+
logger.String("selection_strategy", strategy.Name()),
66+
logger.Int("config_count", len(configs)),
67+
logger.Int("config_order_count", len(configOrder)))
68+
4569
return &TokenManager{
46-
cache: NewSimpleTokenCache(5 * time.Minute),
47-
configs: configs,
70+
cache: NewSimpleTokenCache(5 * time.Minute),
71+
configs: configs,
72+
selectionStrategy: strategy,
73+
configOrder: configOrder,
4874
}
4975
}
5076

@@ -78,31 +104,48 @@ func (tm *TokenManager) getBestToken() (types.TokenInfo, error) {
78104
return bestToken.Token, nil
79105
}
80106

81-
// selectBestToken 选择最优token(简化策略)
107+
// selectBestToken 使用选择策略选择最优token
82108
func (tm *TokenManager) selectBestToken() *CachedToken {
83109
tm.cache.mutex.RLock()
84-
defer tm.cache.mutex.RUnlock()
110+
tokens := tm.cache.tokens // 获取token映射的引用
111+
tm.cache.mutex.RUnlock()
85112

86-
var bestToken *CachedToken
87-
88-
for _, cached := range tm.cache.tokens {
113+
// 过滤出可用的token
114+
availableTokens := make(map[string]*CachedToken)
115+
for key, cached := range tokens {
89116
// 检查token是否过期
90117
if time.Since(cached.CachedAt) > tm.cache.ttl {
91118
continue
92119
}
93120

94121
// 检查token是否可用
95-
if !cached.IsUsable() {
96-
continue
122+
if cached.IsUsable() {
123+
availableTokens[key] = cached
97124
}
125+
}
98126

99-
// 选择可用次数最多的token
100-
if bestToken == nil || cached.Available > bestToken.Available {
101-
bestToken = cached
102-
}
127+
if len(availableTokens) == 0 {
128+
logger.Debug("没有可用的token")
129+
return nil
103130
}
104131

105-
return bestToken
132+
// 使用策略选择token
133+
selectedKey := tm.selectionStrategy.SelectToken(availableTokens)
134+
if selectedKey == "" {
135+
logger.Warn("选择策略未能选择任何token",
136+
logger.String("strategy", tm.selectionStrategy.Name()),
137+
logger.Int("available_count", len(availableTokens)))
138+
return nil
139+
}
140+
141+
selectedToken := availableTokens[selectedKey]
142+
143+
logger.Debug("token选择完成",
144+
logger.String("strategy", tm.selectionStrategy.Name()),
145+
logger.String("selected_key", selectedKey),
146+
logger.Int("available_count", selectedToken.Available))
147+
148+
return selectedToken
106149
}
107150

108151
// refreshCache 刷新token缓存
@@ -212,3 +255,75 @@ func calculateAvailableCount(usage *types.UsageLimits) int {
212255
func CalculateAvailableCount(usage *types.UsageLimits) int {
213256
return calculateAvailableCount(usage)
214257
}
258+
259+
// getTokenSelectionStrategy 从环境变量获取token选择策略
260+
func getTokenSelectionStrategy() TokenSelectionStrategyType {
261+
strategyEnv := strings.ToLower(strings.TrimSpace(os.Getenv("TOKEN_SELECTION_STRATEGY")))
262+
263+
switch strategyEnv {
264+
case "sequential", "sequence", "顺序":
265+
return StrategySequential
266+
case "optimal", "best", "最优":
267+
return StrategyOptimal
268+
case "balanced", "均衡":
269+
return StrategyBalanced
270+
default:
271+
// 默认使用顺序策略(满足用户需求)
272+
return StrategySequential
273+
}
274+
}
275+
276+
// generateConfigOrder 生成token配置的顺序
277+
func generateConfigOrder(configs []AuthConfig) []string {
278+
var order []string
279+
280+
for i := range configs {
281+
// 使用索引生成cache key,与refreshCache中的逻辑保持一致
282+
cacheKey := fmt.Sprintf("token_%d", i)
283+
order = append(order, cacheKey)
284+
}
285+
286+
logger.Debug("生成配置顺序",
287+
logger.Int("config_count", len(configs)),
288+
logger.Any("order", order))
289+
290+
return order
291+
}
292+
293+
// SetSelectionStrategy 动态设置选择策略(用于测试和动态配置)
294+
func (tm *TokenManager) SetSelectionStrategy(strategyType TokenSelectionStrategyType) error {
295+
tm.mutex.Lock()
296+
defer tm.mutex.Unlock()
297+
298+
strategy, err := CreateTokenSelectionStrategy(strategyType, tm.configOrder)
299+
if err != nil {
300+
return fmt.Errorf("创建选择策略失败: %w", err)
301+
}
302+
303+
oldStrategy := tm.selectionStrategy.Name()
304+
tm.selectionStrategy = strategy
305+
306+
logger.Info("token选择策略已更新",
307+
logger.String("old_strategy", oldStrategy),
308+
logger.String("new_strategy", strategy.Name()))
309+
310+
return nil
311+
}
312+
313+
// GetSelectionStrategyStatus 获取选择策略状态(用于监控和调试)
314+
func (tm *TokenManager) GetSelectionStrategyStatus() map[string]interface{} {
315+
tm.mutex.RLock()
316+
defer tm.mutex.RUnlock()
317+
318+
status := map[string]interface{}{
319+
"strategy_name": tm.selectionStrategy.Name(),
320+
"config_order": tm.configOrder,
321+
}
322+
323+
// 如果是顺序策略,获取详细状态
324+
if seqStrategy, ok := tm.selectionStrategy.(*SequentialSelectionStrategy); ok {
325+
status["sequential_status"] = seqStrategy.GetCurrentStatus()
326+
}
327+
328+
return status
329+
}

0 commit comments

Comments
 (0)