# 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 数据模型 ```go // 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 账号创建流程 ```go // 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) ```go // 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 账号状态管理 ```go // 账号状态转换 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 → Error**:TestConnection 失败、请求返回 5xx - **Active → RateLimited**:上游返回 429 - **Active → Expired**:检测到过期时间 - **Any → Disabled**:管理员手动操作 ### 3.5 账号分组管理 ```go // 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 账号用量追踪 ```go // 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 账号预热 ```go // 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 账号健康检查 ```go // 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 账号配额重置 ```go // 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 接口 ```go // 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 查询优化 ```go // 常用查询优化 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) ```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:添加新的账号类型** ```go // 1. 在 domain/constants.go 添加类型 const AccountTypeCustom = "custom" // 2. 在 service/account.go 添加验证 func (a *Account) ValidateCustom() error { // 自定义验证逻辑 } // 3. 在 handler 中添加创建接口 router.POST("/accounts/custom", createCustomAccount) ``` **场景 2:调整账号选择策略** ```go // 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:修改限流行为** ```go // 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*