feat: enforce shared application resource quotas across namespaces

This commit is contained in:
2026-09-17 17:57:54 +08:00
parent 5c8825e4bc
commit 993786476e
43 changed files with 1606 additions and 49 deletions

View File

@@ -0,0 +1,29 @@
-- 停止旧服务后执行。身份与额度分表,避免认证共享锁升级;禁止数据库外键。
CREATE TABLE orbit_application_resources (
application_id BINARY(16) NOT NULL COMMENT '所属应用标识及主键,跨命名空间共享额度',
revision BIGINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '配置乐观版本,用量变化不增加版本',
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间,UTC 微秒',
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '最后配置更新时间,UTC 微秒',
max_unfinished_tasks INT UNSIGNED NOT NULL DEFAULT 1000000 COMMENT '应用未终结任务上限,降额保留已有任务',
unfinished_tasks BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '等待、预占、运行及待核查任务总数,重试不重复计数',
max_concurrency INT UNSIGNED NOT NULL DEFAULT 10000 COMMENT '预占与运行尝试总上限,降额不撤销已有尝试',
active_attempts BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '当前预占与运行尝试总数,结果确认或到期恢复释放',
pending_starts BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已预占但未开始尝试数,包含在活跃尝试中',
rate_per_second INT UNSIGNED NOT NULL DEFAULT 100000 COMMENT '一秒固定窗口内开始授权上限,不是业务请求速率',
start_window_until DATETIME(6) NULL COMMENT '数据库时间的一秒窗口结束时刻,空表示尚未建立窗口',
starts_in_window INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '窗口中已确认的开始次数,重复回执不计数',
PRIMARY KEY (application_id),
CONSTRAINT ck_app_resources_revision CHECK (revision > 0),
CONSTRAINT ck_app_resources_limits CHECK (max_unfinished_tasks > 0 AND max_concurrency > 0 AND rate_per_second > 0),
CONSTRAINT ck_app_resources_pending CHECK (pending_starts <= active_attempts),
CONSTRAINT ck_app_resources_window CHECK (start_window_until IS NOT NULL OR starts_in_window=0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_as_cs COMMENT='应用跨命名空间共享额度与持久化用量,无数据库外键';
INSERT INTO orbit_application_resources(application_id,unfinished_tasks,active_attempts,pending_starts)
SELECT a.id,COALESCE(t.unfinished,0),COALESCE(t.active,0),COALESCE(t.pending,0)
FROM orbit_applications a LEFT JOIN (
SELECT n.application_id,COUNT(*) AS unfinished,
SUM(t.state IN ('LEASED','RUNNING')) AS active,SUM(t.state='LEASED') AS pending
FROM pulse_tasks t JOIN orbit_namespaces n ON n.id=t.namespace_id
WHERE t.state IN ('WAITING','LEASED','RUNNING','NEEDS_REVIEW') GROUP BY n.application_id
) t ON t.application_id=a.id;