mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 09:37:53 +00:00
Update .env.example with new configuration options: - EZ_INTERNAL_ALLOW_ANON for controlling anonymous internal access - EZ_BALANCER_ENABLE_TEST_KEYS for testing auth bypass - EZ_BALANCER_TRUSTED_PROXIES for real IP resolution Add security configuration section to README explaining internal endpoint authentication logic and default behaviors.
203 lines
7.3 KiB
Markdown
203 lines
7.3 KiB
Markdown
# EZ-API (控制平面)
|
||
|
||
EZ-API 网关系统的管理中心和控制平面。
|
||
|
||
## 目标
|
||
|
||
EZ-API 是“控制平面”,负责管理事实来源 (Source of Truth)。
|
||
它主要承担:
|
||
1. **资源管理**:Master/Key/ProviderGroup/APIKey/Model/Binding/Namespace 的 CRUD 与批量操作。
|
||
2. **状态同步**:将配置快照与 Feature Flags 推送到 Redis,供 Balancer 使用。
|
||
3. **日志与统计**:日志摄取/统计、操作日志、实时计数回写。
|
||
4. **运行配置**:CORS、模型注册表、配额重置等运维能力。
|
||
|
||
## 架构设计
|
||
|
||
控制平面采用三层结构,并主动将状态推送到 Redis。
|
||
|
||
- **数据库**: PostgreSQL(主库),可选独立日志库(`EZ_LOG_PG_DSN`)。
|
||
- **缓存/总线**: Redis(配置快照、实时计数、Feature Flags)。
|
||
- **框架**: Gin + GORM。
|
||
|
||
## API 端点
|
||
|
||
> 补充文档(中文):[`docs/api.md`](docs/api.md)
|
||
|
||
### 基础
|
||
- `GET /health`
|
||
- `GET /api/status/test`
|
||
- `GET /swagger/*any`
|
||
|
||
### Internal
|
||
- `POST /internal/stats/flush`:Balancer 统计回写。
|
||
- `GET /internal/metrics`:内部指标。
|
||
|
||
### Admin
|
||
- `/admin/masters`(CRUD + batch + manage)
|
||
- `/admin/masters/:id/realtime`
|
||
- `/admin/masters/:id/keys`
|
||
- `/admin/provider-groups`(CRUD)
|
||
- `/admin/api-keys`(CRUD + batch)
|
||
- `/admin/models`(CRUD + batch)
|
||
- `/admin/bindings`(CRUD + batch)
|
||
- `/admin/namespaces`(CRUD)
|
||
- `/admin/logs`、`/admin/logs/stats`、`/admin/logs/webhook`
|
||
- `/admin/features`、`/admin/operation-logs`、`/admin/stats`
|
||
|
||
### Master
|
||
- `/v1/self`
|
||
- `/v1/tokens`(CRUD)
|
||
- `/v1/logs`、`/v1/logs/stats`
|
||
- `/v1/stats`、`/v1/realtime`
|
||
|
||
### 说明
|
||
- Master 的 `global_qps` 默认 `0` 表示限流关闭;仅当 `global_qps > 0` 才会在数据面生效。
|
||
|
||
## 配置说明
|
||
|
||
| 变量名 | 默认值 | 说明 |
|
||
|--------|--------|------|
|
||
| `EZ_API_PORT` | `8080` | 监听端口。 |
|
||
| `EZ_PG_DSN` | `host=localhost...` | PostgreSQL 主库 DSN。 |
|
||
| `EZ_LOG_PG_DSN` | `` | 日志库 DSN(可选)。 |
|
||
| `EZ_REDIS_ADDR` | `localhost:6379` | Redis 地址。 |
|
||
| `EZ_REDIS_PASSWORD` | `` | Redis 密码。 |
|
||
| `EZ_REDIS_DB` | `0` | Redis DB。 |
|
||
| `EZ_CORS_ALLOW_ORIGINS` | `*` | 允许的 Origin 列表(逗号分隔)。 |
|
||
| `EZ_LOG_QUEUE` | `10000` | 日志缓冲队列容量。 |
|
||
| `EZ_LOG_BATCH_SIZE` | `10` | 单次 DB 写入日志数。 |
|
||
| `EZ_LOG_FLUSH_MS` | `1000` | 日志批量刷新间隔(毫秒)。 |
|
||
| `EZ_LOG_RETENTION_DAYS` | `30` | 日志保留天数。 |
|
||
| `EZ_LOG_MAX_RECORDS` | `1000000` | 日志最大记录数。 |
|
||
| `EZ_LOG_PARTITIONING` | `off` | 日志分区(off/month/day)。 |
|
||
| `EZ_SYNC_OUTBOX_ENABLED` | `true` | CP->Redis 同步失败时启用 outbox 重试。 |
|
||
| `EZ_SYNC_OUTBOX_INTERVAL_SECONDS` | `5` | outbox 重试间隔(秒)。 |
|
||
| `EZ_SYNC_OUTBOX_BATCH_SIZE` | `200` | outbox 单次处理数量。 |
|
||
| `EZ_SYNC_OUTBOX_MAX_RETRIES` | `10` | outbox 最大重试次数。 |
|
||
| `EZ_MODEL_REGISTRY_ENABLED` | `false` | 模型注册表开关。 |
|
||
| `EZ_MODEL_REGISTRY_REFRESH_SECONDS` | `1800` | 模型注册表刷新间隔。 |
|
||
| `EZ_MODEL_REGISTRY_CACHE_DIR` | `./data/model-registry` | 模型注册表缓存目录。 |
|
||
| `EZ_QUOTA_RESET_INTERVAL_SECONDS` | `300` | 配额重置间隔。 |
|
||
| `EZ_INTERNAL_STATS_TOKEN` | `` | 内部统计回写鉴权 token。 |
|
||
| `EZ_INTERNAL_ALLOW_ANON` | `false` | 允许匿名访问 `/internal/*` 端点(仅限开发/测试)。 |
|
||
|
||
### 安全配置说明
|
||
|
||
**内部端点认证 (`/internal/*`)**
|
||
|
||
- 默认情况下,`/internal/*` 端点需要 `X-Internal-Token` 头与 `EZ_INTERNAL_STATS_TOKEN` 匹配。
|
||
- 如果 `EZ_INTERNAL_STATS_TOKEN` 为空且 `EZ_INTERNAL_ALLOW_ANON=false`(默认),所有内部端点请求将返回 401。
|
||
- 仅在开发/测试环境设置 `EZ_INTERNAL_ALLOW_ANON=true` 以允许匿名访问。
|
||
|
||
配置读取优先级:环境变量 > 配置文件 > 默认值。通过 [Viper](https://github.com/spf13/viper) 支持 `./config.yaml`(或 `./config/config.yaml`),也可用 `EZ_CONFIG_FILE` 指定路径。示例:
|
||
|
||
```yaml
|
||
server:
|
||
port: 8080
|
||
postgres:
|
||
dsn: host=localhost user=postgres password=postgres dbname=ezapi port=5432 sslmode=disable
|
||
redis:
|
||
addr: localhost:6379
|
||
db: 0
|
||
log:
|
||
batch_size: 10
|
||
flush_ms: 1000
|
||
queue_capacity: 10000
|
||
auth:
|
||
jwt_secret: change_me_in_production
|
||
```
|
||
|
||
## 运行方式
|
||
|
||
### 本地运行
|
||
|
||
运行前需要准备依赖(Postgres + Redis),否则会出现连接错误
|
||
|
||
建议先启动基础依赖:
|
||
|
||
```bash
|
||
docker compose up -d postgres redis
|
||
```
|
||
|
||
然后在本地设置必要环境变量(可基于 `.env.example`):
|
||
|
||
```bash
|
||
go run cmd/server/main.go
|
||
```
|
||
|
||
### Docker Compose(推荐)
|
||
|
||
在 `ez-api` 目录使用自带的 `docker-compose.yml` 拉起完整栈(Postgres + 日志库 + Redis + ez-api + balancer):
|
||
|
||
```bash
|
||
cd ez-api
|
||
docker compose up -d
|
||
```
|
||
|
||
常用可选变量(写入 `.env`):
|
||
|
||
```env
|
||
EZ_ADMIN_TOKEN=admin123
|
||
EZ_INTERNAL_STATS_TOKEN=internal123
|
||
LOG_POSTGRES_USER=postgres
|
||
LOG_POSTGRES_PASSWORD=postgres
|
||
LOG_POSTGRES_DB=ezapi_logs
|
||
EZ_BALANCER_LOG_SINK_ENABLED=false
|
||
EZ_BALANCER_LOG_SINK_BASE_URL=http://ez-api:8080
|
||
EZ_BALANCER_STATS_FLUSH_ENABLED=false
|
||
EZ_BALANCER_STATS_FLUSH_BASE_URL=http://ez-api:8080
|
||
EZ_BALANCER_STATS_FLUSH_TOKEN=internal123
|
||
```
|
||
|
||
### Docker 单独运行
|
||
|
||
```bash
|
||
docker build -t ez-api .
|
||
docker run -p 8080:8080 --env-file .env ez-api
|
||
```
|
||
|
||
### 本地联合开发(配合 balancer)
|
||
|
||
- 目录结构建议:`/workspace/` 下并列放置 `ez-api`、`balancer`、`foundation`。
|
||
- 初始化本地 Go 工作区(Go 1.20+,不要求提交到任一仓库):在 `/workspace` 执行
|
||
```bash
|
||
go work init
|
||
go work use ./ez-api ./balancer ./foundation
|
||
```
|
||
如果你只使用已发布的 `github.com/ez-api/foundation v0.3.0`(或更高 tag),则不需要 `go.work`。
|
||
|
||
### 集成测试
|
||
|
||
依赖 Docker 与 docker compose,且默认在工作区里与 `balancer` 仓库并列(用于构建镜像)。在仓库内运行:
|
||
|
||
```bash
|
||
cd ez-api
|
||
./test/integration.sh
|
||
```
|
||
|
||
脚本会拉起 `docker-compose.integration.yml` 中的服务,运行带 `integration` tag 的 Go 测试,并在完成后清理容器和卷。
|
||
|
||
## 测试
|
||
|
||
- 单元测试:`go test ./...`(测试文件与源码同目录,更多约定见 `TESTING.md`)
|
||
|
||
## 日志
|
||
|
||
- 业务代码统一使用标准库 `log/slog`(`logger.Info("msg", "k", v)` 风格)。
|
||
- 输出后端仍为 [zerolog](https://github.com/rs/zerolog)(通过 `github.com/ez-api/foundation/logging` 的 slog handler bridge),默认 ConsoleWriter。
|
||
- 通过 `EZ_LOG_LEVEL` 控制控制平面的日志等级,配合异步 DB 写入(LogWriter)一起使用。
|
||
|
||
## JSON
|
||
|
||
- 项目内 JSON 编解码统一走 `github.com/ez-api/foundation/jsoncodec`(内部使用 Sonic)。
|
||
|
||
## 依赖约定
|
||
|
||
- Control Plane(ez-api)与 Data Plane(balancer)共享一部分“协议约定/基础设施”代码(JSON、日志、provider type 规则),统一沉淀在 `github.com/ez-api/foundation`。
|
||
- 本仓库的 `go.mod` 需要依赖一个可用的 `foundation` 版本:发布后建议锁定到 `v0.3.0`(或更高 tag);本地联调可使用 `go.work`(见下文)。
|
||
|
||
## 设计决策
|
||
|
||
- **异步日志**: 日志不会立即写入 DB。它们被缓冲在内存中,并分批刷新,以减少 DB IOPS。
|
||
- **快照同步**: Balancer 不查询 DB,而是由 EZ-API 将 JSON 快照推送到 Redis。这将高流量的数据平面与关系型数据库解耦。
|