refactor: 优化优先级管理和路由展示功能

- 支持按 API 格式设置不同的全局优先级,替换单一 global_priority 字段为 global_priority_by_format
- 路由标签根据调度模式动态显示(缓存亲和/负载均衡/固定顺序)
- 优先级管理对话框 UI 优化:紧凑布局、活跃/停用状态分组排序、快捷启用/禁用开关
- 优先级管理对话框包含所有 Key(含停用的),支持快速切换状态
- 优化配置更新流程:先保存优先级数据,再切换调度模式,避免瞬态不一致
- 调度相关配置缓存 TTL 从 60 秒降至 5 秒,确保多 Worker 快速收敛
- 配置更新时立即同步当前 Worker 的 Scheduler 状态
This commit is contained in:
fawney19
2026-02-09 18:21:34 +08:00
parent b14fb31933
commit 7f7f569148
6 changed files with 220 additions and 133 deletions

View File

@@ -712,13 +712,10 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
db = context.db
# Key 属于 Provider按 key.api_formats 分组展示
# 包含所有 Key含停用的 Key 和停用的 Provider前端可显示停用标签和快捷开关
keys = (
db.query(ProviderAPIKey, Provider)
.join(Provider, ProviderAPIKey.provider_id == Provider.id)
.filter(
ProviderAPIKey.is_active.is_(True),
Provider.is_active.is_(True),
)
.order_by(
ProviderAPIKey.internal_priority.asc(),
)
@@ -789,6 +786,7 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
"global_priority_by_format": key.global_priority_by_format,
"rate_multipliers": key.rate_multipliers,
"is_active": key.is_active,
"provider_active": provider.is_active,
"provider_name": provider.name,
"api_formats": api_formats,
"capabilities": caps_list,

View File

@@ -634,6 +634,38 @@ class AdminSetSystemConfigAdapter(AdminApiAdapter):
except Exception as e:
logger.warning(f"更新用户配额重置任务时间失败: {e}")
# 如果更新的是调度模式或优先级模式,立即更新当前 Worker 的 Scheduler 单例
if self.key in ("scheduling_mode", "provider_priority_mode"):
try:
from src.clients.redis_client import get_redis_client_sync
from src.services.cache.aware_scheduler import get_cache_aware_scheduler
redis_client = get_redis_client_sync()
# 从数据库读取两个调度配置的最新值,确保一致性
priority_mode = SystemConfigService.get_config(
context.db,
"provider_priority_mode",
"provider",
)
scheduling_mode = SystemConfigService.get_config(
context.db,
"scheduling_mode",
"cache_affinity",
)
await get_cache_aware_scheduler(
redis_client,
priority_mode=priority_mode,
scheduling_mode=scheduling_mode,
)
logger.info(
"[AdminSetSystemConfig] 已同步更新 Scheduler: "
"priority_mode={}, scheduling_mode={}",
priority_mode,
scheduling_mode,
)
except Exception as e:
logger.warning("同步更新 Scheduler 失败: {}", e)
# 返回时不暴露加密后的值
display_value = "********" if self.key in self.ENCRYPTED_KEYS else config.value

View File

@@ -29,6 +29,13 @@ class RequestRecordLevel(str, Enum):
# 进程内缓存 TTL- 系统配置变化不频繁,使用较长的 TTL
_CONFIG_CACHE_TTL = 60 # 1 分钟
# 调度相关配置使用更短的缓存 TTL确保多 Worker 部署时快速收敛
# 当管理员切换调度模式时,其他 Worker 最多延迟 5 秒即可感知变更
_SCHEDULING_CONFIG_CACHE_TTL = 5 # 5 秒
# 需要跨 Worker 快速同步的调度相关配置 key
SCHEDULING_CONFIG_KEYS = frozenset({"scheduling_mode", "provider_priority_mode"})
# 进程内缓存存储: {key: (value, expire_time)}
_config_cache: dict[str, tuple[Any, float]] = {}
@@ -49,8 +56,12 @@ def _get_cached_config(key: str) -> tuple[bool, Any]:
def _set_cached_config(key: str, value: Any) -> None:
"""设置进程内缓存"""
_config_cache[key] = (value, time.time() + _CONFIG_CACHE_TTL)
"""设置进程内缓存
调度相关配置使用更短的 TTL5秒确保多 Worker 部署时快速收敛。
"""
ttl = _SCHEDULING_CONFIG_CACHE_TTL if key in SCHEDULING_CONFIG_KEYS else _CONFIG_CACHE_TTL
_config_cache[key] = (value, time.time() + ttl)
def invalidate_config_cache(key: str | None = None) -> None: