diff --git a/gateway/README.md b/gateway/README.md index 124444fe..45d0e77d 100644 --- a/gateway/README.md +++ b/gateway/README.md @@ -6,11 +6,13 @@ - 服务入口是 `cmd/gateway/main.go`。 - 当前对外暴露的主要接口是 `/v1/chat/completions`、`/v1/completions`、`/v1/models`,以及对应的 `/api/v1/*` 兼容路径。 +- `/v1/models` 现在返回当前已注册 provider 的模型并集,按模型 ID 去重后排序,不再返回硬编码静态列表。 - 鉴权运行时支持两种模式: - `inmemory` - `remote_introspection` - provider 注册已经从配置装配;如果未显式配置 provider,启动时会基于环境变量生成默认 OpenAI provider。 - 审计发射器支持 PostgreSQL 与内存实现;数据库未配置时会显式回退到内存实现。 +- 生产环境必须显式提供 `PASSWORD_ENCRYPTION_KEY` 与 `GATEWAY_CORS_ALLOW_ORIGINS`;缺省密钥和 `*` CORS 只允许在开发态使用。 ## 与其他服务的边界 @@ -39,13 +41,21 @@ export GATEWAY_TOKEN_RUNTIME_URL="http://127.0.0.1:18081" 默认监听 `0.0.0.0:8080`。 +生产环境额外要求: + +```bash +export GATEWAY_ENV="production" +export PASSWORD_ENCRYPTION_KEY="32-byte-production-secret........" +export GATEWAY_CORS_ALLOW_ORIGINS="https://console.example.com,https://app.example.com" +``` + ## 验证命令 模块级验证: ```bash cd "/home/long/project/立交桥/gateway" -GOCACHE=/tmp/lijiaoqiao-go-cache-gateway go test ./... +go test -count=1 ./... ``` 仓库级统一验证: @@ -61,3 +71,9 @@ bash scripts/ci/repo_integrity_check.sh - `internal/handler/`:OpenAI 兼容 HTTP handler。 - `internal/middleware/`:鉴权、CORS、远程 introspection。 - `internal/router/`:provider 路由、打分与 fallback。 + +## 路由策略说明 + +- 主启动链路当前只接入 `latency`、`round_robin`、`weighted`、`availability` 四种策略。 +- `internal/router/strategy/cost_based.go`、`internal/router/strategy/cost_aware.go` 与 `internal/router/fallback/` 仍属于实验性模块,没有接入 `BuildServer` 的运行时装配。 +- 如果配置里填入未接入的策略名,启动链路会回退到 `latency`。 diff --git a/gateway/internal/app/bootstrap.go b/gateway/internal/app/bootstrap.go index f0cbce96..3379dccf 100644 --- a/gateway/internal/app/bootstrap.go +++ b/gateway/internal/app/bootstrap.go @@ -168,6 +168,8 @@ func buildTokenRuntime(cfg config.AuthConfig) (interface { } } +// resolveStrategy 只暴露当前主启动链路已验证的策略。 +// cost_based、cost_aware 与 fallback 仍停留在实验模块,未接入 BuildServer。 func resolveStrategy(strategy string) router.LoadBalancerStrategy { switch strings.ToLower(strings.TrimSpace(strategy)) { case string(router.StrategyRoundRobin): diff --git a/gateway/internal/app/bootstrap_test.go b/gateway/internal/app/bootstrap_test.go index fe4cc96b..b5b8309d 100644 --- a/gateway/internal/app/bootstrap_test.go +++ b/gateway/internal/app/bootstrap_test.go @@ -6,6 +6,7 @@ import ( "testing" "lijiaoqiao/gateway/internal/config" + "lijiaoqiao/gateway/internal/router" ) func TestBuildServer_FromConfigProviders(t *testing.T) { @@ -118,6 +119,15 @@ func TestBuildServer_DevelopmentAllowsDefaultSecurityFallbacks(t *testing.T) { } } +func TestResolveStrategy_ExperimentalStrategiesFallbackToLatency(t *testing.T) { + tests := []string{"cost_based", "cost_aware", "fallback"} + for _, strategy := range tests { + if got := resolveStrategy(strategy); got != router.StrategyLatency { + t.Fatalf("strategy %s should fallback to latency, got %s", strategy, got) + } + } +} + func buildServerWithoutPanic(t *testing.T, cfg *config.Config) (_ *http.Server, err error) { t.Helper()