chore(project): 初始化项目基础配置和开发计划

This commit is contained in:
yangzhaohan
2026-07-08 18:47:40 +08:00
parent b334137900
commit ea1dd4876d
5 changed files with 770 additions and 1 deletions
+466
View File
@@ -0,0 +1,466 @@
# Janus - AI 中转站 完整开发计划
## Context
构建一个 AI API 中转/网关服务(Janus),使用 Go + Gin + PostgreSQLGORM),前端采用前后端分离架构(Vue 3)。
用户背景:Java 转 Go,项目兼顾学习目的。计划按阶段递增复杂度,每个阶段引入新的 Go 语言特性:
- 早期:struct、interface、error handling、package 组织
- 中期:goroutine、channel、sync 包(并发安全)
- 后期:middleware 模式、context、observability
## 架构总览
```
┌─────────────────────────────────────────────────┐
│ Clients │
│ (OpenAI SDK / Anthropic SDK / curl) │
└─────────────────┬───────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Janus Gateway │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Gin │ │ Proxy │ │ Management │ │
│ │ Router │ │ Engine │ │ API (CRUD) │ │
│ └────┬─────┘ └────┬─────┘ └───────┬───────┘ │
│ │ │ │ │
│ ┌────┴─────────────┴───────────────┴───────┐ │
│ │ Service Layer │ │
│ │ ┌──────────┐ ┌────────┐ ┌────────────┐ │ │
│ │ │ Balancer │ │ Health │ │ Rate Limiter│ │ │
│ │ │ Service │ │Checker │ │ Service │ │ │
│ │ └──────────┘ └────────┘ └────────────┘ │ │
│ └────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────────────┴──────────────────────────┐ │
│ │ Repository Layer (GORM) │ │
│ └────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────────────┴──────────────────────────┐ │
│ │ PostgreSQL │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Vue 3 Dashboard (SPA) │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Upstream AI Providers │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ OpenAI │ │Anthropic │ │ Compatible │ │
│ │ API │ │ API │ │ (DS, QWen) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────────┘
```
## 项目目录结构
```
janus/
├── cmd/
│ └── server/
│ └── main.go # 应用入口,依赖组装
├── internal/
│ ├── config/
│ │ └── config.go # YAML 配置加载(viper
│ ├── model/
│ │ ├── provider.go # Provider 模型
│ │ ├── api_key.go # ApiKey 模型
│ │ ├── model.go # AIModel 模型
│ │ └── request_log.go # RequestLog 模型
│ ├── repository/
│ │ ├── provider_repo.go # Provider CRUD
│ │ ├── api_key_repo.go # ApiKey CRUD
│ │ ├── model_repo.go # AIModel CRUD
│ │ └── request_log_repo.go # Log 查询
│ ├── service/
│ │ ├── provider_svc.go # Provider 业务逻辑
│ │ ├── api_key_svc.go # ApiKey 管理
│ │ ├── balancer_svc.go # 负载均衡核心
│ │ ├── proxy_svc.go # 请求代理引擎
│ │ ├── health_svc.go # 健康检查 & 故障转移
│ │ └── rate_limit_svc.go # 速率限制
│ ├── handler/
│ │ ├── proxy_handler.go # /v1/* 代理端点
│ │ ├── provider_handler.go # Provider 管理 API
│ │ ├── api_key_handler.go # ApiKey 管理 API
│ │ ├── model_handler.go # Model 管理 API
│ │ ├── stats_handler.go # 统计 API
│ │ └── health_handler.go # 健康检查
│ ├── middleware/
│ │ ├── auth.go # API Key 认证
│ │ ├── ratelimit.go # 速率限制中间件
│ │ ├── logging.go # 请求日志中间件
│ │ ├── cors.go # CORS
│ │ └── recovery.go # Panic 恢复
│ ├── proxy/
│ │ ├── openai.go # OpenAI 协议适配器
│ │ ├── anthropic.go # Anthropic 协议适配器
│ │ └── adapter.go # 适配器接口定义
│ ├── balancer/
│ │ ├── strategy.go # 策略接口
│ │ ├── round_robin.go # 轮询实现
│ │ └── weighted.go # 加权实现
│ ├── health/
│ │ ├── checker.go # 健康检查 Worker
│ │ └── circuit_breaker.go # 熔断器
│ └── router/
│ └── router.go # 路由注册
├── pkg/
│ ├── response/
│ │ └── response.go # 统一响应格式
│ ├── errors/
│ │ └── errors.go # 自定义错误类型
│ └── utils/
│ └── utils.go # 工具函数
├── web/ # Vue 3 前端项目
│ ├── src/
│ │ ├── views/
│ │ ├── components/
│ │ ├── api/
│ │ └── router/
│ ├── package.json
│ └── vite.config.ts
├── migrations/ # 数据库迁移 SQL
│ ├── 001_init.up.sql
│ └── 001_init.down.sql
├── config.yaml # 默认配置
└── go.mod
```
## 数据库设计
```sql
-- providers: AI 服务提供商
CREATE TABLE providers (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE, -- openai / anthropic / deepseek
base_url VARCHAR(255) NOT NULL, -- https://api.openai.com
protocol VARCHAR(20) NOT NULL DEFAULT 'openai', -- openai / anthropic
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active / disabled
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- api_keys: API 密钥池
CREATE TABLE api_keys (
id BIGSERIAL PRIMARY KEY,
provider_id BIGINT NOT NULL REFERENCES providers(id),
key_value TEXT NOT NULL, -- 加密存储
name VARCHAR(100), -- 别名/备注
weight INT NOT NULL DEFAULT 1, -- 负载权重
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled/depleted
fail_count INT NOT NULL DEFAULT 0, -- 连续失败计数
last_used_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- models: 可用模型列表
CREATE TABLE models (
id BIGSERIAL PRIMARY KEY,
provider_id BIGINT NOT NULL REFERENCES providers(id),
name VARCHAR(100) NOT NULL, -- gpt-4o / claude-sonnet-4-5
input_price DECIMAL(10,8) DEFAULT 0, -- 每 1K token 价格
output_price DECIMAL(10,8) DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'active',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(provider_id, name)
);
-- request_logs: 请求日志
CREATE TABLE request_logs (
id BIGSERIAL PRIMARY KEY,
api_key_id BIGINT,
model_id BIGINT,
provider_id BIGINT,
request_method VARCHAR(10),
request_path VARCHAR(500),
request_body TEXT,
response_body TEXT,
status_code INT,
latency_ms INT,
tokens_in INT DEFAULT 0,
tokens_out INT DEFAULT 0,
cost DECIMAL(10,6) DEFAULT 0,
error_message TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 索引
CREATE INDEX idx_api_keys_provider_id ON api_keys(provider_id);
CREATE INDEX idx_api_keys_status ON api_keys(status);
CREATE INDEX idx_models_provider_id ON models(provider_id);
CREATE INDEX idx_request_logs_created_at ON request_logs(created_at DESC);
CREATE INDEX idx_request_logs_provider_id ON request_logs(provider_id);
```
## API 设计
### 代理端点(OpenAI 兼容 & Anthropic 兼容)
```
POST /v1/chat/completions # OpenAI 聊天补全
POST /v1/embeddings # OpenAI 嵌入
POST /v1/messages # Anthropic Messages API
GET /v1/models # 列出可用模型(聚合所有 provider)
```
### 管理 APIDashboard 用)
```
# Providers
GET /api/admin/providers
POST /api/admin/providers
GET /api/admin/providers/:id
PUT /api/admin/providers/:id
DELETE /api/admin/providers/:id
# API Keys
GET /api/admin/api-keys?provider_id=
POST /api/admin/api-keys
PUT /api/admin/api-keys/:id
DELETE /api/admin/api-keys/:id
POST /api/admin/api-keys/:id/toggle # 启用/禁用
# Models
GET /api/admin/models?provider_id=
POST /api/admin/models
PUT /api/admin/models/:id
DELETE /api/admin/models/:id
# Stats
GET /api/admin/stats/overview # 总览统计
GET /api/admin/stats/requests # 请求明细
```
## 负载均衡 & 故障转移设计
### 负载策略接口
```go
type Strategy interface {
Next(keys []*model.ApiKey) *model.ApiKey
Name() string
}
```
### 策略实现
1. **RoundRobin** - 无状态轮询,适合均匀分布
2. **WeightedRoundRobin** - 按 weight 字段加权分配
### 健康检查
- 每个 ApiKey 维护 `fail_count` 连续失败计数
- 失败超过阈值(默认 3 次)自动标记为 `disabled`
- 后台 goroutine 定期重试 disabled 的 key30s 间隔)
- 正常请求也作为隐式健康检查
### 故障转移流程
1. Balancer 选取一个 ApiKey
2. 代理请求到上游
3. 如果失败(5xx / 超时 / 网络错误):
- 递增 `fail_count`
- 达到阈值标记 `disabled`
- 立即从剩余 key 中选择重试(最多 3 次)
4. 如果成功:重置 `fail_count` 为 0
### 熔断器(单例 per ApiKey
```
状态机: CLOSED → (连续失败) → OPEN → (冷却时间) → HALF_OPEN → (成功) → CLOSED
→ (失败) → OPEN
```
## 分阶段实施计划
### Phase 1: 项目骨架 & 基础设施(第 1-2 天)
**学习目标**: Go 项目组织、package 管理、Gin 基础
具体任务:
- [-] 初始化 `go.mod`go mod init github.com/synoth/janus
- [ ] 安装核心依赖:gin, gorm, viper, pgx 驱动
- [ ] 实现 `internal/config/config.go`Viper 加载 YAML 配置
- [ ] 编写 `config.yaml`:数据库连接、服务器端口等
- [ ] 实现 `cmd/server/main.go`:组装依赖,启动 Gin
- [ ] 实现 `internal/router/router.go`:基础路由
- [ ] 实现 `internal/handler/health_handler.go`GET /health
- [ ] 实现 GORM 数据库连接 & AutoMigrate
- [ ] 添加 `.env` 支持敏感配置
**交付物**: 可运行的服务,响应 `/health`,连接数据库
### Phase 2: 数据模型 & Repository 层(第 2-3 天)
**学习目标**: Go struct、GORM 关系映射、interface 定义
具体任务:
- [ ] 定义 `internal/model/provider.go`struct + GORM 标签)
- [ ] 定义 `internal/model/api_key.go`
- [ ] 定义 `internal/model/model.go`AIModel
- [ ] 定义 `internal/model/request_log.go`
- [ ] 编写 SQL 迁移脚本 `migrations/001_init.up.sql`
- [ ] 实现 `internal/repository/provider_repo.go`CRUD
- [ ] 实现 `internal/repository/api_key_repo.go`
- [ ] 实现 `internal/repository/model_repo.go`
- [ ] 编写 Repository 层的单元测试
**交付物**: 完整的数据访问层,可通过测试验证
### Phase 3: Provider & API Key 管理 API(第 3-4 天)
**学习目标**: Gin handler、请求验证、JSON 序列化、统一错误处理
具体任务:
- [ ] 实现 `pkg/response/response.go`:统一 JSON 响应格式
- [ ] 实现 `pkg/errors/errors.go`:业务错误码定义
- [ ] 实现 `internal/service/provider_svc.go`
- [ ] 实现 `internal/service/api_key_svc.go`
- [ ] 实现 `internal/handler/provider_handler.go`CRUD API
- [ ] 实现 `internal/handler/api_key_handler.go`CRUD API
- [ ] 实现 `internal/handler/model_handler.go`:模型管理 API
- [ ] 添加请求验证(binding tags + validator
- [ ] Postman/curl 可测试的完整管理 API
**交付物**: 可通过 REST API 管理 Provider、ApiKey、Model
### Phase 4: 代理引擎(第 4-6 天)
**学习目标**: HTTP 反向代理、streaming、context、Go http.Client
具体任务:
- [ ] 实现 `internal/proxy/adapter.go`:协议适配器接口
```go
type Adapter interface {
Forward(ctx context.Context, key *model.ApiKey, body []byte) (*ProxyResult, error)
Protocol() string
}
```
- [ ] 实现 `internal/proxy/openai.go`OpenAI 请求转发
- 支持 `/v1/chat/completions`(含 streaming
- 支持 `/v1/embeddings`
- [ ] 实现 `internal/proxy/anthropic.go`Anthropic 请求转发
- 支持 `/v1/messages`(含 streaming
- [ ] 实现 `internal/service/proxy_svc.go`:编排代理流程
- [ ] 实现 `internal/handler/proxy_handler.go`
- 解析请求路径确定目标 protocol
- 从 header 获取 Janus API Key → 查找 upstream key 池
- 调用代理服务
- [ ] 实现 `internal/middleware/auth.go`Janus 自身的 API Key 认证
- [ ] 添加请求日志记录(写入 request_logs
- [ ] 处理 streaming 响应(SSE
**交付物**: 可以用 curl 通过 Janus 调用 OpenAI/Anthropic
### Phase 5: 负载均衡(第 6-7 天)
**学习目标**: Go interface 多态、sync.Mutex、原子操作
具体任务:
- [ ] 实现 `internal/balancer/strategy.go`Strategy 接口
- [ ] 实现 `internal/balancer/round_robin.go`
- 线程安全的轮询计数器(sync.Mutex 或 atomic
- 跳过 disabled key
- [ ] 实现 `internal/balancer/weighted.go`
- 加权轮询算法
- 平滑加权轮询(Nginx 算法)
- [ ] 实现 `internal/service/balancer_svc.go`
- 集成策略选择(可通过 API 或配置切换)
- 从 DB 加载可用 key 列表(带缓存)
- [ ] 修改 ProxyService 集成 BalancerService
- [ ] 编写负载均衡的单元测试(验证分布均匀性)
**交付物**: 请求自动在多个 ApiKey 间负载均衡
### Phase 6: 健康检查 & 故障转移(第 7-9 天)
**学习目标**: Goroutine、Channel、context 取消、并发模式
具体任务:
- [ ] 实现 `internal/health/circuit_breaker.go`
- 三态状态机(Closed/Open/HalfOpen
- 可配置阈值和冷却时间
- [ ] 实现 `internal/health/checker.go`
- 后台 goroutine 定期检查 disabled key
- 向每个 provider 发送轻量健康检查请求
- 通过 channel 接收检查结果
- [ ] 实现 `internal/service/health_svc.go`
- 管理所有 key 的健康状态
- 优雅关闭(context 取消 → 停止所有 goroutine
- [ ] 修改 ProxyService 添加故障转移逻辑:
- 请求失败 → 标记 key → 从剩余池中重试
- 最大重试次数 3
- 熔断器介入
- [ ] 添加健康状态 APIGET /api/admin/keys/:id/health
**交付物**: 单个 key 故障时自动切换,故障 key 自动恢复
### Phase 7: 速率限制 & 可观测性(第 9-10 天)
**学习目标**: Middleware 模式、token bucket 算法、结构化日志
具体任务:
- [ ] 实现 `internal/service/rate_limit_svc.go`
- Token bucket 算法(golang.org/x/time/rate
- 支持按 Janus API Key 限流
- 支持按上游模型限流
- [ ] 实现 `internal/middleware/ratelimit.go`
- 从 Gin context 提取 key
- 返回 429 Too Many Requests
- 添加 Retry-After header
- [ ] 实现 `internal/middleware/logging.go`
- 结构化日志(使用 slog 或 zerolog
- 记录 latency、status、path、tokens
- [ ] 实现 `internal/middleware/recovery.go`Panic 恢复
- [ ] 实现 `internal/handler/stats_handler.go`
- 总请求数、成功率、平均延迟
- 按 Provider/Model 分组统计
- 费用汇总
- [ ] 添加 `internal/middleware/cors.go`
**交付物**: 完整的中间件链,可观测的统计数据
### Phase 8: Dashboard 前端 & 容器化(第 10-14 天)
**学习目标**: 前后端集成、Docker、项目收尾
具体任务:
- [ ] 初始化 Vue 3 + Vite 项目(`web/`
- [ ] 安装 UI 组件库(Element Plus 或 Naive UI
- [ ] 实现 Providers 管理页面
- [ ] 实现 API Keys 管理页面
- [ ] 实现 Models 管理页面
- [ ] 实现统计仪表盘页面(图表)
- [ ] 前端构建产物由 Gin 静态文件服务托管
- [ ] 编写 Dockerfile(多阶段构建)
- [ ] 编写 docker-compose.ymlJanus + PostgreSQL
- [ ] 编写 README.md(中英文)
**交付物**: 完整的可部署项目
## Go 学习路径映射
| Phase | Go 特性 | Java 对比 |
|-------|---------|-----------|
| 1 | package, import, func, defer | package ≈ package, defer ≈ finally |
| 2 | struct, interface, 指针 | struct ≈ class(无继承), interface 隐式满足 |
| 3 | error handling, type assertion | error 返回值 ≠ exception |
| 4 | context, http.Client, io.Reader | context ≈ 请求上下文传递 |
| 5 | sync.Mutex, atomic, slice | 无内置锁语法,需显式使用 |
| 6 | goroutine, channel, select | ≈ ThreadPool + BlockingQueue |
| 7 | middleware 闭包, functional options | ≈ Filter chain / Builder pattern |
| 8 | 前后端集成, Docker | 通用技能 |
## 关键技术决策
1. **配置管理**: Viper(支持 YAML + 环境变量覆盖)
2. **ORM**: GORM v2AutoMigrate 用于开发,生产用迁移脚本)
3. **API Key 加密**: 使用 AES-256-GCM 加密存储 key_value
4. **Streaming**: 使用 `http.Flusher` + SSE 协议
5. **日志**: slogGo 1.21+ 内置结构化日志)
6. **前端**: Vue 3 + Vite + Element Plus(轻量、国内文档丰富)
7. **容器化**: 多阶段 Docker 构建,docker-compose 一键部署
## 验证方式
每个 Phase 完成后的验证方法:
1. `go build ./...` 编译通过
2. `go vet ./...` 静态分析通过
3. `go test ./...` 单元测试通过
4. curl / Postman 手动测试关键 API
5. Phase 4+ 可用 OpenAI SDK 指向 Janus 实际调用
6. Phase 6 手动停用一个 key 验证故障转移
7. Phase 8 `docker-compose up` 一键启动