feat(routing): 引入多执行池智能调度

将 Worker 发现、路由画像、容量与执行传输抽象为平台无关接口,新增 Kubernetes 和静态容量适配器,并以 shadow 模式接入生产配置。

实现网络与容量评分、路由防抖、池队列、同步 Worker 租约、一次性执行令牌,以及提交状态不明时禁止重复分配的安全语义。

新增 0105 兼容迁移、管理接口、指标、OpenAPI 和回归测试。已执行全量 Go 测试、go vet、OpenAPI、迁移安全、Compose 与 Kustomize 验证。
This commit is contained in:
2026-08-05 22:25:37 +08:00
parent 03c0873649
commit 7786692d32
58 changed files with 4510 additions and 348 deletions
@@ -32,8 +32,8 @@ type KubernetesClient struct {
client *http.Client
}
type KubernetesSiteState struct {
Site string
type PoolInfrastructureState struct {
PoolID string
NodeName string
CurrentReplicas int
Revision string
@@ -45,10 +45,10 @@ type KubernetesSiteState struct {
UsedMilliCPU int64
WorkerRequestMilliCPU int64
MemoryPressure bool
Nodes []KubernetesNodeState
Nodes []PoolNodeState
}
type KubernetesNodeState struct {
type PoolNodeState struct {
NodeName string
CurrentReplicas int
AllocatableMemoryBytes int64
@@ -60,6 +60,25 @@ type KubernetesNodeState struct {
MemoryPressure bool
}
type KubernetesSiteState = PoolInfrastructureState
type KubernetesNodeState = PoolNodeState
var _ OrchestratorAdapter = (*KubernetesClient)(nil)
func (client *KubernetesClient) PoolState(ctx context.Context, poolID, adapterRef string) (PoolInfrastructureState, error) {
state, err := client.SiteState(ctx, adapterRef)
state.PoolID = poolID
return state, err
}
func (client *KubernetesClient) ScalePool(ctx context.Context, _, adapterRef string, replicas int) error {
return client.ScaleWorkerDeployment(ctx, adapterRef, replicas)
}
func (client *KubernetesClient) SetInstanceTerminationPriority(ctx context.Context, instanceRef string, priority int) error {
return client.SetPodDeletionCost(ctx, instanceRef, priority)
}
func NewKubernetesClient(config KubernetesConfig) (*KubernetesClient, error) {
if strings.TrimSpace(config.Namespace) == "" {
return nil, errors.New("capacity controller Kubernetes namespace is required")
@@ -144,7 +163,7 @@ func (client *KubernetesClient) SiteState(ctx context.Context, site string) (Kub
if err := client.getJSON(ctx, deploymentPath, &deployment); err != nil {
return KubernetesSiteState{}, err
}
state := KubernetesSiteState{Site: site, CurrentReplicas: deployment.Spec.Replicas}
state := KubernetesSiteState{PoolID: site, CurrentReplicas: deployment.Spec.Replicas}
for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name != "worker" {
continue