mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-06-26 03:51:28 +08:00
功能: v2.2 节点池调度 + Grafana Dashboard + 版本漂移 UI (#49)
节点池动态调度(企业集群核心需求): - model.Node 新增 Labels CSV;Node.HasLabel / LabelSet 辅助方法 - model.BackupTask 新增 NodePoolTag;与 NodeID 互斥(校验层拒绝同时设置) - BackupExecutionService.selectPoolNode:匹配标签的在线节点中选"运行中任务最少" 并列按 ID 升序稳定;空池返回 NODE_POOL_EMPTY 让用户立即感知 - 选中节点仅写 BackupRecord,不回写 task.NodeID —— 每次执行重选实现真轮转均衡 Grafana Dashboard(v2.1 指标的可视化闭环): - deploy/grafana/backupx-dashboard.json:11 个面板覆盖概览/时序/容量/集群 - deploy/grafana/README.md:Prometheus 抓取配置 + 告警建议 - release workflow 打包 grafana/ + nginx.conf 到 tar.gz 前端: - 节点列表:Agent 版本 vs Master 不一致时橙红 Tag + Tooltip 提示升级 - 节点列表新增"标签/节点池"列,支持 CSV 编辑 + 并发/带宽一起改 - 任务表单新增 NodePoolTag 输入框,与节点选择器互斥禁用 测试: - model/node_label_test.go:HasLabel / LabelSet / nil 安全 - service/node_pool_scheduler_test.go:负载最低优先 / 空池错误 / nil repo 降级 - go test ./... + npm run build 全绿
This commit is contained in:
@@ -59,6 +59,7 @@ function createEmptyDraft(storageTargets?: StorageTargetSummary[]): BackupTaskPa
|
||||
storageTargetId: defaultIds[0] ?? 0,
|
||||
storageTargetIds: defaultIds,
|
||||
nodeId: 0,
|
||||
nodePoolTag: '',
|
||||
tags: '',
|
||||
retentionDays: 30,
|
||||
compression: 'gzip',
|
||||
@@ -127,6 +128,7 @@ export function BackupTaskFormDrawer({ visible, loading, initialValue, storageTa
|
||||
storageTargetId: editTargetIds[0] ?? 0,
|
||||
storageTargetIds: editTargetIds,
|
||||
nodeId: (initialValue as any).nodeId ?? 0,
|
||||
nodePoolTag: (initialValue as any).nodePoolTag ?? '',
|
||||
tags: initialValue.tags ?? '',
|
||||
retentionDays: initialValue.retentionDays,
|
||||
compression: initialValue.compression,
|
||||
@@ -297,12 +299,28 @@ export function BackupTaskFormDrawer({ visible, loading, initialValue, storageTa
|
||||
<Select
|
||||
value={draft.nodeId ?? 0}
|
||||
options={nodeOptions}
|
||||
onChange={(value) => updateDraft({ nodeId: Number(value ?? 0) })}
|
||||
onChange={(value) => {
|
||||
const nodeId = Number(value ?? 0)
|
||||
// 固定节点与节点池互斥:切到固定节点时清空 NodePoolTag
|
||||
updateDraft(nodeId > 0 ? { nodeId, nodePoolTag: '' } : { nodeId })
|
||||
}}
|
||||
/>
|
||||
<Typography.Paragraph type="secondary" style={{ marginBottom: 0, marginTop: 4 }}>
|
||||
任务在所选节点上执行备份与恢复;源路径/数据库以该节点视角解析。远程节点需先在"节点管理"中安装 Agent。
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
<div>
|
||||
<Typography.Text>节点池标签(可选)</Typography.Text>
|
||||
<Input
|
||||
placeholder="填写标签后从节点池动态调度(与固定节点互斥)"
|
||||
value={draft.nodePoolTag ?? ''}
|
||||
disabled={(draft.nodeId ?? 0) > 0}
|
||||
onChange={(value) => updateDraft({ nodePoolTag: value })}
|
||||
/>
|
||||
<Typography.Paragraph type="secondary" style={{ marginBottom: 0, marginTop: 4 }}>
|
||||
执行节点选"本机 / 未指定"时可启用;从节点 Labels 命中此 tag 的在线节点中按当前运行任务数最少的挑选一台执行。
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
<div>
|
||||
<Typography.Text>Cron 表达式</Typography.Text>
|
||||
<CronInput value={draft.cronExpr} onChange={(value) => updateDraft({ cronExpr: value })} />
|
||||
|
||||
Reference in New Issue
Block a user