Files
tokens-reef/deploy/docs-backup/MODULE_03_ACCOUNT.md
Developer 349d783fd1 refactor: clean up project structure
- Remove old review reports (keep latest only)
- Move docs/ to deploy/docs-backup/
- Move performance-testing/ to deploy/
- Clean up test output files
- Organize root directory
2026-04-06 23:36:03 +08:00

12 KiB
Raw Permalink Blame History

Sub2API 模块分析报告:账户管理模块

1. 模块概述

1.1 模块定位

账户管理模块是 Sub2API 的上游资源管理核心,负责管理连接到 AI 服务提供商的账号Account。这些账号是系统转发请求的"上游凭证",包括 OAuth 授权账号、API Key 账号等。

1.2 核心职责

  • 账号 CRUD:创建、读取、更新、删除上游账号
  • 账号状态管理:监控账号健康、处理限流和过期
  • 分组管理:将账号分组以实现资源隔离和配额控制
  • 账号测试验证账号有效性TestConnection

2. 代码结构分析

2.1 核心文件

文件路径 职责 代码行数
service/account.go 账号实体定义和服务基础 ~800 行
service/account_service.go 账号管理核心逻辑 ~1200 行
service/account_group.go 分组管理服务 ~500 行
service/account_usage_service.go 账号用量监控 ~400 行
service/account_expiry_service.go 账号过期管理 ~300 行
handler/admin/account_handler.go 账号管理 API ~1900 行
repository/account_repo.go 账号数据访问层 ~1800 行

2.2 数据模型

// ent/schema/account.go
type Account struct {
    ID              int64     // 主键
    Platform        string    // 平台anthropic/openai/gemini/antigravity/bedrock
    Type            string    // 类型oauth/apikey
    Name            string    // 账号名称(显示用)
    Credentials     string    // 加密凭证JSON
    Extra           string    // 额外配置JSON
    Status          string    // 状态active/error/disabled/expired
    GroupID         int64     // 所属分组
    RateMultiplier  float64   // 计费倍率
    MaxConcurrency  int       // 最大并发
    BaseURL         string    // 自定义上游地址
    CreatedAt       time.Time
    UpdatedAt       time.Time
}

3. 功能详细分析

3.1 账号类型支持

平台 类型 认证方式 特性
Anthropic OAuth / API Key Bearer Token Claude 模型支持
OpenAI API Key Bearer Token ChatGPT、GPT 模型
Google Gemini API Key Bearer Token 多模态支持
Antigravity OAuth 独立认证系统 独立配额
AWS Bedrock API Key AWS 签名 v4 Claude on Bedrock

3.2 账号创建流程

// service/account_service.go - CreateAccount
func (s *AccountService) CreateAccount(ctx context.Context, req CreateAccountRequest) (*Account, error) {
    // 1. 验证请求参数
    if err := validateAccountRequest(req); err != nil {
        return nil, err
    }
    
    // 2. 加密凭证
    encryptedCreds, err := s.encryptCredentials(req.Credentials)
    if err != nil {
        return nil, err
    }
    
    // 3. 创建账号
    account := &Account{
        Platform:   req.Platform,
        Type:      req.Type,
        Name:      req.Name,
        Credentials: encryptedCreds,
        GroupID:   req.GroupID,
        Status:    StatusActive,
    }
    
    // 4. 保存到数据库
    return s.accountRepo.Create(ctx, account)
}

3.3 账号验证 (TestConnection)

// service/account_test_service.go - TestAccount
func (s *AccountTestService) TestAccount(ctx context.Context, account *Account) (*TestResult, error) {
    // 1. 构建测试请求
    testReq := buildTestRequest(account)
    
    // 2. 发送请求
    resp, err := s.sendRequest(ctx, account, testReq)
    if err != nil {
        return &TestResult{
            Success: false,
            Error:   err.Error(),
        }, nil
    }
    
    // 3. 检查响应
    if !isSuccessResponse(resp) {
        return &TestResult{
            Success: false,
            StatusCode: resp.StatusCode,
            Error:   parseError(resp.Body),
        }, nil
    }
    
    // 4. 解析响应(获取配额信息)
    quota := parseQuotaInfo(resp.Body)
    return &TestResult{
        Success:     true,
        QuotaInfo:  quota,
        StatusCode: 200,
    }, nil
}

验证端点:

平台 测试端点 验证内容
Anthropic /v1/messages 基本连通性 + 配额
OpenAI /v1/models 模型列表
Gemini /v1/models 模型列表
Antigravity /v1/models 模型列表
Bedrock /invocations 基本连通性

3.4 账号状态管理

// 账号状态转换
const (
    StatusActive    = "active"     // 正常可用
    StatusError     = "error"      // 出错(临时)
    StatusDisabled  = "disabled"  // 管理员禁用
    StatusExpired   = "expired"    // 已过期
    StatusRateLimited = "rate_limited" // 被限流
)

// 状态检查
func (a *Account) CanUse() bool {
    return a.Status == StatusActive || a.Status == StatusRateLimited
}

状态变更触发:

  • Active → ErrorTestConnection 失败、请求返回 5xx
  • Active → RateLimited:上游返回 429
  • Active → Expired:检测到过期时间
  • Any → Disabled:管理员手动操作

3.5 账号分组管理

// service/account_group.go
type Group struct {
    ID              int64
    Name            string
    Platform        string    // 平台类型
    Status          string
    RateMultiplier  float64   // 计费倍率
    MaxConcurrency  int      // 分组最大并发
    Models          []string  // 允许的模型列表
    IsExclusive     bool      // 独占模式(只能被单个用户使用)
}

分组特性:

  • 按平台隔离:不同平台使用不同分组
  • 模型限制:分组可限定可用模型
  • 独占模式:某些分组只允许单个用户访问
  • 计费倍率:不同分组可有不同计费策略

3.6 账号用量追踪

// service/account_usage_service.go
func (s *AccountUsageService) RecordUsage(ctx context.Context, accountID int64, tokens int, cost float64) error {
    // 1. 更新内存统计
    s.localStats.Add(accountID, tokens, cost)
    
    // 2. 更新 Redis 统计
    s.redisStats.Incr(accountID, tokens, cost)
    
    // 3. 定期同步到数据库
    if s.shouldSync(accountID) {
        s.syncToDB(accountID)
    }
    return nil
}

// 获取当前负载
func (s *AccountUsageService) GetLoadFactor(accountID int64) float64 {
    activeConns := s.GetActiveConnections(accountID)
    maxConns := s.GetMaxConcurrency(accountID)
    return float64(activeConns) / float64(maxConns)
}

4. 高级功能

4.1 账号预热

// service/account_intercept_warmup.go
// 新账号首次使用前进行预热请求
func WarmupAccount(account *Account) error {
    // 发送轻量级请求建立连接
    req := &Request{
        Model:  "claude-3-haiku-20240307",  // 最小的模型
        MaxTokens: 1,
    }
    
    resp, err := sendRequest(account, req)
    if err != nil {
        return err
    }
    
    // 预热后更新状态
    account.Status = StatusActive
    return nil
}

4.2 账号健康检查

// service/account_health_check.go
func (s *HealthCheckService) CheckAccount(accountID int64) {
    account := s.getAccount(accountID)
    
    // 检查最后活跃时间
    if time.Since(account.LastUsedAt) > 24*time.Hour {
        // 超过 24 小时未使用,发送探测请求
        s.testAccount(account)
    }
    
    // 检查过期时间
    if account.ExpiresAt != nil && time.Now().After(*account.ExpiresAt) {
        s.updateStatus(accountID, StatusExpired)
    }
}

4.3 账号配额重置

// service/account_quota_reset.go
func (s *QuotaResetService) ResetDailyQuota() {
    // 每天 UTC 0 点重置
    for _, account := range s.getAllAccounts() {
        account.UsageToday = 0
        account.UpdatedAt = time.Now()
        s.accountRepo.Update(account)
    }
}

5. 数据访问层

5.1 Repository 接口

// repository/account_repo.go
type AccountRepository interface {
    Create(ctx context.Context, account *Account) (*Account, error)
    GetByID(ctx context.Context, id int64) (*Account, error)
    GetByGroupID(ctx context.Context, groupID int64) ([]*Account, error)
    Update(ctx context.Context, account *Account) error
    Delete(ctx context.Context, id int64) error
    
    // 高级查询
    GetAvailableAccounts(ctx context.Context, groupID int64) ([]*Account, error)
    Search(ctx context.Context, filters AccountFilters) ([]*Account, error)
}

5.2 查询优化

// 常用查询优化
func (r *accountRepository) GetAvailableAccounts(ctx context.Context, groupID int64) ([]*Account, error) {
    return r.client.Account.Query().
        Where(
            account.GroupID(groupID),
            account.StatusEQ("active"),
            account.DeletedAtIsNil(),
        ).
        All(ctx)
}

6. 配置参数

6.1 账号配置config.yaml

account:
  # 账号健康检查
  health_check:
    enabled: true
    interval: 5m
    timeout: 30s
    
  # 账号预热
  warmup:
    enabled: true
    model: "claude-3-haiku-20240307"
    
  # 配额重置
  quota_reset:
    timezone: "UTC"
    hour: 0
    
  # 限流配置
  rate_limit:
    window: 60s
    max_errors: 3
    reset_after: 300s

6.2 环境变量

变量 说明 默认值
ACCOUNT_HEALTH_CHECK_ENABLED 启用健康检查 true
ACCOUNT_WARMUP_ENABLED 启用预热 true
ACCOUNT_MAX_CONCURRENCY 默认最大并发 10

7. 修改和扩展指南

7.1 常见修改场景

场景 1添加新的账号类型

// 1. 在 domain/constants.go 添加类型
const AccountTypeCustom = "custom"

// 2. 在 service/account.go 添加验证
func (a *Account) ValidateCustom() error {
    // 自定义验证逻辑
}

// 3. 在 handler 中添加创建接口
router.POST("/accounts/custom", createCustomAccount)

场景 2调整账号选择策略

// service/account_service.go - SelectAccount
func (s *AccountService) SelectAccount(ctx context.Context, groupID int64, model string) (*Account, error) {
    // 调整选择逻辑
    accounts := s.getAvailableAccounts(groupID)
    
    // 按负载排序
    sort.Slice(accounts, func(i, j int) bool {
        return accounts[i].LoadFactor < accounts[j].LoadFactor
    })
    
    return accounts[0], nil
}

场景 3修改限流行为

// service/account_service.go - HandleRateLimit
func (s *AccountService) HandleRateLimit(accountID int64, resetAfter time.Duration) error {
    // 修改限流持续时间
    account, _ := s.GetByID(accountID)
    account.Status = StatusRateLimited
    account.RateLimitedAt = time.Now()
    account.RateLimitResetAt = time.Now().Add(resetAfter * 2)  // 倍增
    
    return s.Update(account)
}

7.2 注意事项

  1. 凭证安全:账号凭证必须加密存储,密钥独立管理
  2. 并发安全:账号选择需要考虑并发场景
  3. 状态一致性:账号状态变更需要同步到缓存

8. 测试覆盖

8.1 单元测试

测试文件 覆盖范围
account_service_test.go 账号 CRUD
account_load_factor_test.go 负载计算
account_expiry_service_test.go 过期处理
account_test_service_openai_test.go OpenAI 测试

8.2 集成测试

测试文件 场景
e2e_gateway_test.go 账号选择和请求转发

9. 监控与运维

9.1 关键指标

指标 告警阈值 说明
account_error_count > 10 账号错误数
account_rate_limited > 20% 账号限流比例
account_expired > 5% 账号过期比例
account_test_success_rate < 90% 测试成功率

9.2 运维任务

任务 频率 说明
健康检查 5 分钟 检查账号可用性
配额重置 每天 重置每日用量
过期检查 每天 检查账号过期时间
统计同步 每小时 同步用量到数据库

10. 总结

账户管理模块特点:

  • 多平台支持:统一接口管理多种 AI 服务账号
  • 状态自动化:自动处理限流、过期等状态
  • 分组隔离:通过分组实现资源隔离和配额控制
  • 健康监控:持续的账号健康检查和预热

潜在改进点:

  1. 账号测试可以更全面(模拟实际请求)
  2. 支持更多账号配置选项(代理、超时等)

修改建议:

  • 账号类型扩展相对简单,风险较低
  • 状态管理逻辑修改需充分测试

文档版本1.0 最后更新2025-01 分析基于Sub2API v0.1.104