feat(routing): 引入多执行池智能调度
将 Worker 发现、路由画像、容量与执行传输抽象为平台无关接口,新增 Kubernetes 和静态容量适配器,并以 shadow 模式接入生产配置。 实现网络与容量评分、路由防抖、池队列、同步 Worker 租约、一次性执行令牌,以及提交状态不明时禁止重复分配的安全语义。 新增 0105 兼容迁移、管理接口、指标、OpenAPI 和回归测试。已执行全量 Go 测试、go vet、OpenAPI、迁移安全、Compose 与 Kustomize 验证。
This commit is contained in:
@@ -198,42 +198,27 @@ func TestProcessRolePrecedenceAndCompatibility(t *testing.T) {
|
||||
|
||||
func TestWorkerAutoscalingConfiguration(t *testing.T) {
|
||||
t.Setenv("AI_GATEWAY_WORKER_AUTOSCALING_ENABLED", "true")
|
||||
t.Setenv("AI_GATEWAY_WORKER_REPLICAS_NINGBO", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_REPLICAS_HONGKONG", "2")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MIN_REPLICAS_NINGBO", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MIN_REPLICAS_HONGKONG", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MAX_REPLICAS_NINGBO", "2")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MAX_REPLICAS_HONGKONG", "3")
|
||||
t.Setenv("AI_GATEWAY_CAPACITY_POOLS", `[{"id":"pool-a","bootstrapReplicas":2,"minReplicas":1,"maxReplicas":3}]`)
|
||||
cfg := Load()
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("valid autoscaling configuration was rejected: %v", err)
|
||||
}
|
||||
if !cfg.WorkerAutoscalingEnabled || cfg.WorkerReplicasHongkong != 2 || cfg.WorkerMaxReplicasHongkong != 3 {
|
||||
pools, err := cfg.CapacityPools()
|
||||
if err != nil || !cfg.WorkerAutoscalingEnabled || len(pools) != 1 || pools[0].BootstrapReplicas != 2 || pools[0].MaxReplicas != 3 {
|
||||
t.Fatalf("autoscaling configuration=%+v", cfg)
|
||||
}
|
||||
cfg.WorkerReplicasHongkong = 4
|
||||
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "bootstrap") {
|
||||
cfg.CapacityPoolsJSON = `[{"id":"pool-a","bootstrapReplicas":4,"minReplicas":1,"maxReplicas":3}]`
|
||||
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "invalid pool") {
|
||||
t.Fatalf("Validate() error=%v, want bootstrap bound failure", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkerTopologyDefaultsToNingboSingleNode(t *testing.T) {
|
||||
for _, name := range []string{
|
||||
"AI_GATEWAY_WORKER_REPLICAS_NINGBO",
|
||||
"AI_GATEWAY_WORKER_REPLICAS_HONGKONG",
|
||||
"AI_GATEWAY_WORKER_MIN_REPLICAS_NINGBO",
|
||||
"AI_GATEWAY_WORKER_MIN_REPLICAS_HONGKONG",
|
||||
"AI_GATEWAY_WORKER_MAX_REPLICAS_NINGBO",
|
||||
"AI_GATEWAY_WORKER_MAX_REPLICAS_HONGKONG",
|
||||
} {
|
||||
t.Setenv(name, "")
|
||||
}
|
||||
func TestWorkerTopologyHasNoBuiltInSites(t *testing.T) {
|
||||
t.Setenv("AI_GATEWAY_CAPACITY_POOLS", "")
|
||||
cfg := Load()
|
||||
if cfg.WorkerReplicasNingbo != 1 || cfg.WorkerMinReplicasNingbo != 1 || cfg.WorkerMaxReplicasNingbo != 1 {
|
||||
t.Fatalf("Ningbo Worker defaults=%d/%d/%d, want 1/1/1", cfg.WorkerReplicasNingbo, cfg.WorkerMinReplicasNingbo, cfg.WorkerMaxReplicasNingbo)
|
||||
}
|
||||
if cfg.WorkerReplicasHongkong != 0 || cfg.WorkerMinReplicasHongkong != 0 || cfg.WorkerMaxReplicasHongkong != 0 {
|
||||
t.Fatalf("Hong Kong Worker defaults=%d/%d/%d, want disabled", cfg.WorkerReplicasHongkong, cfg.WorkerMinReplicasHongkong, cfg.WorkerMaxReplicasHongkong)
|
||||
pools, err := cfg.CapacityPools()
|
||||
if err != nil || len(pools) != 0 {
|
||||
t.Fatalf("default pools=%+v error=%v, want no built-in sites", pools, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +390,7 @@ func TestLoadAndValidateDirectMediaOSS(t *testing.T) {
|
||||
func TestCapacityControllerDoesNotRequireMediaOSSCredentials(t *testing.T) {
|
||||
cfg := Load()
|
||||
cfg.ProcessRole = "capacity-controller"
|
||||
cfg.CapacityPoolsJSON = `[{"id":"pool-a","bootstrapReplicas":1,"minReplicas":1,"maxReplicas":1}]`
|
||||
cfg.MediaOSSDirectEnabled = true
|
||||
cfg.MediaOSSAccessKeyID = ""
|
||||
cfg.MediaOSSAccessKeySecret = ""
|
||||
|
||||
Reference in New Issue
Block a user