feat(worker): 实现集群限流与自适应负载
保留平台模型 RPM、TPM 和并发策略语义,增加 PostgreSQL 集群级租约、饱和候选重选和多平台自动负载,避免突发任务固定等待首个平台。\n\n新增 Worker 实时负载采样、自适应 active/heavy 容量、心跳与管理端指标,并扩展本地 acceptance runner,覆盖三 Worker、同模型三平台 2/4/6 并发和 48 个带图视频突发任务。\n\n验证:go test ./...、go vet ./...、PostgreSQL 跨 Store 集成测试、gofmt、bash -n、ShellCheck 及本地集群 provider-burst 验收通过;48/48 成功,无越限、重复提交、重复计费、重复回调或终态资源泄漏。
This commit is contained in:
@@ -57,7 +57,7 @@ func TestDistributedAdmissionModelTypeBoundary(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptanceAdmissionScopesUseWorkerCapacityInsteadOfSupplierConcurrency(t *testing.T) {
|
||||
func TestAcceptanceAdmissionScopesIsolateRunWithoutChangingLimits(t *testing.T) {
|
||||
input := []store.AdmissionScope{{
|
||||
ScopeType: "platform_model",
|
||||
ScopeKey: "model-1",
|
||||
@@ -70,15 +70,15 @@ func TestAcceptanceAdmissionScopesUseWorkerCapacityInsteadOfSupplierConcurrency(
|
||||
ConcurrentLimit: 48,
|
||||
}}
|
||||
|
||||
got := acceptanceAdmissionScopes(store.GatewayTask{RunMode: "acceptance"}, input)
|
||||
got := acceptanceAdmissionScopes(store.GatewayTask{RunMode: "acceptance", AcceptanceRunID: "run-1"}, input)
|
||||
|
||||
if got[0].ConcurrentLimit != 0 {
|
||||
t.Fatalf("protocol-emulated acceptance must defer to worker capacity, got %+v", got[0])
|
||||
if got[0].ConcurrentLimit != 10 || got[0].ScopeKey != "acceptance:run-1:model-1" {
|
||||
t.Fatalf("protocol-emulated acceptance must preserve the limit in an isolated scope, got %+v", got[0])
|
||||
}
|
||||
if got[0].QueueLimit != acceptanceQueueLimit || got[0].MaxWaitSeconds != acceptanceQueueMaxWait {
|
||||
t.Fatalf("acceptance must enable a bounded queue, got %+v", got[0])
|
||||
}
|
||||
if got[1].ConcurrentLimit != 48 {
|
||||
if got[1].ConcurrentLimit != 48 || got[1].ScopeKey != "acceptance:run-1:global" {
|
||||
t.Fatalf("acceptance worker capacity changed, got %+v", got[1])
|
||||
}
|
||||
if input[0].QueueLimit != 0 || input[0].MaxWaitSeconds != 0 {
|
||||
@@ -100,15 +100,15 @@ func TestAcceptanceCanaryPreservesProductionConcurrency(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptanceInfrastructureReservationsOnlyRemoveSupplierConcurrency(t *testing.T) {
|
||||
func TestAcceptanceInfrastructureReservationsIsolateEveryMetric(t *testing.T) {
|
||||
input := []store.RateLimitReservation{
|
||||
{ScopeType: "platform_model", Metric: "concurrent", Limit: 10},
|
||||
{ScopeType: "platform_model", Metric: "rpm", Limit: 600},
|
||||
{ScopeType: "user_group", Metric: "concurrent", Limit: 20},
|
||||
{ScopeType: "platform_model", ScopeKey: "model-1", Metric: "concurrent", Limit: 10},
|
||||
{ScopeType: "platform_model", ScopeKey: "model-1", Metric: "rpm", Limit: 600},
|
||||
{ScopeType: "user_group", ScopeKey: "group-1", Metric: "concurrent", Limit: 20},
|
||||
}
|
||||
|
||||
got := acceptanceInfrastructureReservations(store.GatewayTask{RunMode: "acceptance"}, input)
|
||||
if len(got) != 2 || got[0].Metric != "rpm" || got[1].ScopeType != "user_group" {
|
||||
got := acceptanceInfrastructureReservations(store.GatewayTask{RunMode: "acceptance", AcceptanceRunID: "run-1"}, input)
|
||||
if len(got) != 3 || got[0].ScopeKey != "acceptance:run-1:model-1" || got[1].ScopeKey != "acceptance:run-1:model-1" || got[2].ScopeKey != "acceptance:run-1:group-1" {
|
||||
t.Fatalf("unexpected acceptance reservations: %+v", got)
|
||||
}
|
||||
canary := acceptanceInfrastructureReservations(store.GatewayTask{RunMode: "acceptance_canary"}, input)
|
||||
@@ -192,6 +192,28 @@ func TestPinCandidatesToTaskAdmissionPreservesWaitingCandidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPinCandidatesToTaskAdmissionAllowsRequestedReselection(t *testing.T) {
|
||||
input := []store.RuntimeModelCandidate{
|
||||
{PlatformID: "platform-a", PlatformModelID: "model-a"},
|
||||
{PlatformID: "platform-b", PlatformModelID: "model-b"},
|
||||
}
|
||||
admission := &store.TaskAdmission{
|
||||
Status: "waiting",
|
||||
PlatformID: "platform-b",
|
||||
PlatformModelID: "model-b",
|
||||
ReselectRequestedAt: time.Now(),
|
||||
}
|
||||
|
||||
got, pinned := pinCandidatesToTaskAdmission(input, admission)
|
||||
|
||||
if pinned {
|
||||
t.Fatalf("reselection request unexpectedly pinned the old candidate: %+v", got)
|
||||
}
|
||||
if got[0].PlatformModelID != "model-a" {
|
||||
t.Fatalf("reselection changed the sorted candidate order: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPinCandidatesToTaskAdmissionIgnoresMissingCandidate(t *testing.T) {
|
||||
input := []store.RuntimeModelCandidate{
|
||||
{PlatformID: "platform-a", PlatformModelID: "model-a"},
|
||||
|
||||
Reference in New Issue
Block a user