浏览器只通过 HttpOnly Cookie 恢复统一认证状态,不再访问认证中心 Token Endpoint 或保存 OIDC Token。同步更新错误提示、部署配置和接入文档。
152 lines
7.4 KiB
Markdown
152 lines
7.4 KiB
Markdown
# EasyAI AI Gateway
|
||
|
||
独立的 AI 网关中台脚手架,用于把现有 `integration-platform` 的平台管理、模型路由、计费预估、队列执行、Chat / 生图 / 生视频等生成能力逐步从 `easyai-server-main` 拆成可独立运行的项目。
|
||
|
||
## 技术选型
|
||
|
||
- 后端:Go + PostgreSQL 18,复用 Agent memory 的 `easyai-pgvector`,支持本地用户、可选邀请码、API Key、余额/充值闭环,也支持复用 `server-main` 的 JWT / API Key 授权语义。
|
||
- 前端:React + TypeScript + TSX,UI 体系按 `shadcn-ui` / Radix / Tailwind 方向沉淀,先提供运维控制台骨架。
|
||
- Monorepo:Nx 负责任务编排,Go 使用 `go.work` 管理模块。
|
||
- 集成:完成后由 `easyai-server-main` 通过内部 HTTP SDK 直连本服务;任务实时进度由 Gateway 回调 `server-main`,再通过原 WebSocket 网关推送给业务前端。
|
||
|
||
## 目录
|
||
|
||
```text
|
||
apps/
|
||
api/ Go HTTP API, auth middleware, PG store, migrations
|
||
web/ React TSX admin console
|
||
packages/
|
||
contracts/ Shared TypeScript DTO contracts
|
||
docs/
|
||
design.md Detailed architecture and migration design
|
||
```
|
||
|
||
## 本地启动
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
pnpm install
|
||
pnpm dev
|
||
```
|
||
|
||
服务默认地址:
|
||
|
||
- API: `http://localhost:8088`
|
||
- Web: `http://localhost:5178`
|
||
- PostgreSQL: 目标版本 18,默认使用宿主机 `localhost:5432` 上的 `easyai-pgvector` 实例,并使用独立库 `easyai_ai_gateway`
|
||
- 身份模式: 默认 `IDENTITY_MODE=hybrid`,可同时测试 Gateway 本地账号注册登录、可选邀请码和 `server-main` JWT / API Key 对接。
|
||
|
||
### Auth Center OIDC 受控 JIT
|
||
|
||
OIDC 用户通过签名、Issuer、Audience、`tid`、Scope 和应用角色校验后,Gateway 可在首个受保护请求前创建本地业务投影。该投影只用于 Gateway 的用户组、钱包、API Key、任务归属和审计,不修改 Auth Center Claims,也不迁移或合并历史账号。
|
||
|
||
```dotenv
|
||
OIDC_ENABLED=true
|
||
OIDC_JIT_PROVISIONING_ENABLED=true
|
||
OIDC_GATEWAY_TENANT_KEY=default
|
||
OIDC_BROWSER_SESSION_ENABLED=true
|
||
OIDC_SESSION_COOKIE_SECURE=false # 本地 HTTP;生产必须为 true
|
||
OIDC_CLIENT_ID=<公共 Client ID>
|
||
OIDC_REDIRECT_URI=http://localhost:8088/api/v1/auth/oidc/callback
|
||
OIDC_POST_LOGOUT_REDIRECT_URI=http://localhost:5178/
|
||
OIDC_SESSION_ENCRYPTION_KEY=<base64 编码的独立 32 字节随机密钥>
|
||
```
|
||
|
||
`OIDC_GATEWAY_TENANT_KEY` 必须指向已有且启用的 Gateway 租户及其默认用户组;JIT 不会从 Token 自动创建租户。开关默认关闭,关闭后不再创建新用户,但仍可解析此前创建的 `source=oidc` 映射。
|
||
|
||
Web Console 使用公共 Client + PKCE + Gateway BFF Session:Gateway 服务端换码并加密保存 Access/Refresh/ID Token,浏览器 JavaScript 只持有不可读的 HttpOnly 随机 Session Cookie。Access Token 仍为 5 分钟并由业务请求按需刷新;Session 闲置 30 分钟、最长 8 小时。Gateway 不使用 Client Secret,也不二次签发 JWT。完整行为、错误码和回滚方式见 [OIDC JIT 接入说明](docs/oidc-jit-provisioning.md)。
|
||
|
||
`pnpm dev` 会先创建数据库并执行 migration,然后并行启动:
|
||
|
||
- `api:dev`:通过 `scripts/go-watch.mjs` 运行 Go API,监听 `.go`、`go.mod`、`go.sum` 变化并自动重启后端进程;watcher 会按进程组终止旧的 `go run` 和其子进程,避免热更新时残留进程占用 API 端口。
|
||
- `web:dev`:Vite React dev server。
|
||
|
||
后端热更新可通过 `GO_WATCH_SHUTDOWN_GRACE_MS` 和 `GO_WATCH_RESTART_DELAY_MS` 调整旧进程退出等待时间与重启间隔。
|
||
|
||
## Docker Compose 一键部署
|
||
|
||
仓库内提供了面向 `linux/amd64` 的 Docker Compose 构建和部署脚本,会自动构建 API/Web 镜像、启动 PostgreSQL、执行数据库迁移,并验证 API 与 Web 是否可访问:
|
||
|
||
```bash
|
||
scripts/deploy-compose.sh
|
||
```
|
||
|
||
部署成功后默认访问地址:
|
||
|
||
- Web: `http://127.0.0.1:5178`
|
||
- API: `http://127.0.0.1:8088/healthz`
|
||
- Web 反代 API: `http://127.0.0.1:5178/gateway-api/healthz`
|
||
|
||
常用覆盖项:
|
||
|
||
```bash
|
||
AI_GATEWAY_IMAGE_TAG=2026.05.23-1 scripts/deploy-compose.sh
|
||
AI_GATEWAY_IMAGE_TAG=2026.05.23-1 AI_GATEWAY_PUSH=1 scripts/deploy-compose.sh
|
||
AI_GATEWAY_IMAGE_TAG=2026.05.23-1 scripts/deploy-compose.sh push
|
||
AI_GATEWAY_WEB_PORT=8080 AI_GATEWAY_API_PORT=18088 scripts/deploy-compose.sh
|
||
AI_GATEWAY_GO_PROXY='https://proxy.golang.org,direct' scripts/deploy-compose.sh
|
||
AI_GATEWAY_SKIP_BUILD=1 scripts/deploy-compose.sh
|
||
scripts/deploy-compose.sh down
|
||
scripts/deploy-compose.sh clean
|
||
```
|
||
|
||
默认镜像地址为:
|
||
|
||
- API: `registry.cn-shanghai.aliyuncs.com/easyaigc/ai-gateway:latest`
|
||
- Web: `registry.cn-shanghai.aliyuncs.com/easyaigc/ai-gateway-web:latest`
|
||
|
||
执行 `scripts/deploy-compose.sh push` 或设置 `AI_GATEWAY_PUSH=1` 时,会同时推送当前版本 tag 和 `latest`。当前版本 tag 优先使用 `AI_GATEWAY_IMAGE_TAG`;如果没有设置,则使用根 `package.json` 里的 `version`。
|
||
|
||
推送前需要先登录阿里云镜像仓库:
|
||
|
||
```bash
|
||
docker login --username=<your-aliyun-account> registry.cn-shanghai.aliyuncs.com
|
||
```
|
||
|
||
Web 容器的 Nginx 配置通过 bind mount 挂载自仓库文件 [docker/nginx.conf](docker/nginx.conf),可直接修改该文件调整静态资源和 `/gateway-api` 反向代理配置。修改后执行以下命令使配置生效:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.yml restart web
|
||
```
|
||
|
||
Compose 默认使用独立容器数据库 `postgres:18-alpine`,数据卷会保留在 `postgres_data` 和 `api_data`。为避免本地开发 `.env` 中的 `localhost` 数据库地址污染容器部署,compose 使用 `AI_GATEWAY_COMPOSE_*` 变量作为容器部署专用覆盖,例如:
|
||
|
||
```bash
|
||
AI_GATEWAY_COMPOSE_DATABASE_URL='postgresql://easyai:easyai2025@postgres:5432/easyai_ai_gateway?sslmode=disable' scripts/deploy-compose.sh
|
||
```
|
||
|
||
数据库迁移仍通过 `migrator` 容器执行,但脚本使用 `docker compose run --rm migrator`,迁移成功后不会留下 `migrator-1 Exited` 容器。
|
||
|
||
## OpenAPI 文档
|
||
|
||
修改 `apps/api/internal/httpapi` 下的接口、请求或响应类型后,请重新执行:
|
||
|
||
```bash
|
||
pnpm openapi
|
||
```
|
||
|
||
|
||
默认 EasyAI 部署里,`easyai-pgvector` 在容器网络内的连接串是:
|
||
|
||
```dotenv
|
||
AI_GATEWAY_DATABASE_URL=postgresql://easyai:easyai2025@easyai-pgvector:5432/easyai_ai_gateway?schema=public
|
||
```
|
||
|
||
宿主机直跑时需要使用宿主机可访问的 Postgres 地址。如果 `easyai-pgvector` 将 `5432` 映射到了本机,可使用:
|
||
|
||
```dotenv
|
||
AI_GATEWAY_DATABASE_URL=postgresql://easyai:easyai2025@localhost:5432/easyai_ai_gateway?sslmode=disable
|
||
```
|
||
|
||
如果现有 `easyai-pgvector` 没有把 `5432` 映射到宿主机,就需要补端口映射,或者把 AI Gateway 后端容器化后接入同一个 `easyai` Docker network。
|
||
|
||
## 迁移原则
|
||
|
||
1. 新服务先并行运行,不直接删除 `easyai-server-main` 内现有模块。
|
||
2. 身份域支持 `standalone`、`server-main`、`hybrid` 三种模式;独立模式由 Gateway 维护租户、用户、用户组、本地 API Key、余额和充值订单,接入模式从 `server-main` 同步租户、用户和用户组。
|
||
3. OpenAPI `sk-*` 校验、文件上传、扣费结算在接入模式下仍由 `server-main` 承担;独立模式走 Gateway 本地闭环。
|
||
4. 网关服务负责基准模型库、平台模型路由、用户组调用折扣、TPM/RPM/并发限流、任务队列、三方平台执行、任务进度事件和回调 outbox。
|
||
5. 切流时优先让 `server-main` 的 `OpenaiService` 变成薄门面,内部调用本服务。
|
||
|
||
详细设计见 [docs/design.md](docs/design.md)。
|