mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
fix: 治理 Prometheus 指标基数爆炸和内存缓存无界增长
- 移除 token/latency Prometheus 指标的 model 标签,避免 provider x model 笛卡尔积 - HealthMonitor 滑动窗口从 DB JSON 迁移至进程内存,减少写放大 - ModelCostService 三层缓存增加 500 条上限,超限时清空 - StickyPriority 粘性缓存和健康状态字典增加容量淘汰 - AffinityManager 请求锁字典增加 500 条上限,淘汰空闲锁 - 配额刷新/探测查询使用 defer/load_only 避免加载大 JSON 列 - Alembic 迁移清理 DB 中遗留的 request_results_window 数据 - 同步更新测试适配 batch_get_cooldowns 返回值和批量删除异步化
This commit is contained in:
@@ -78,10 +78,12 @@ class StickyPriorityStrategy(LoadBalancerStrategy):
|
||||
"total_failures": 0,
|
||||
}
|
||||
)
|
||||
self._max_provider_health_entries: int = 200 # 上限,防止无界增长
|
||||
|
||||
# 当前粘性提供商缓存 {cache_key: provider_id}
|
||||
# cache_key 可以是 api_key_id 或者其他标识
|
||||
self._sticky_providers: dict[str, str] = {}
|
||||
self._max_sticky_entries: int = 2000 # 上限,防止无界增长
|
||||
|
||||
# 统计信息
|
||||
self._stats = {
|
||||
@@ -260,6 +262,12 @@ class StickyPriorityStrategy(LoadBalancerStrategy):
|
||||
|
||||
# 没有缓存或缓存失效,选择权重最大的
|
||||
sticky_candidate = max(candidates, key=lambda c: c.weight)
|
||||
# 超出上限时清理不在当前候选列表中的旧条目
|
||||
if len(self._sticky_providers) >= self._max_sticky_entries:
|
||||
active_ids = {str(c.provider.id) for c in candidates}
|
||||
stale = [k for k, v in self._sticky_providers.items() if v not in active_ids]
|
||||
for k in stale[: len(stale) // 2 or len(stale)]:
|
||||
del self._sticky_providers[k]
|
||||
self._sticky_providers[cache_key] = str(sticky_candidate.provider.id)
|
||||
|
||||
logger.info(f"Set new sticky provider {sticky_candidate.provider.name}")
|
||||
@@ -358,6 +366,17 @@ class StickyPriorityStrategy(LoadBalancerStrategy):
|
||||
error: 错误信息(如果失败)
|
||||
"""
|
||||
provider_id = str(provider.id)
|
||||
# 超出上限时淘汰健康且请求量最少的条目
|
||||
if (
|
||||
provider_id not in self._provider_health
|
||||
and len(self._provider_health) >= self._max_provider_health_entries
|
||||
):
|
||||
healthy_keys = [
|
||||
k for k, v in self._provider_health.items() if v["is_healthy"] and k != provider_id
|
||||
]
|
||||
if healthy_keys:
|
||||
victim = min(healthy_keys, key=lambda k: self._provider_health[k]["total_requests"])
|
||||
del self._provider_health[victim]
|
||||
health_info = self._provider_health[provider_id]
|
||||
|
||||
health_info["total_requests"] += 1
|
||||
|
||||
@@ -209,7 +209,7 @@ class MonitorPlugin(BasePlugin):
|
||||
def record_token_usage(
|
||||
self,
|
||||
provider: str,
|
||||
model: str,
|
||||
model: str, # noqa: ARG002 - 保留签名兼容性,不再用于 Prometheus 标签
|
||||
input_tokens: int,
|
||||
output_tokens: int,
|
||||
cost: float | None = None,
|
||||
@@ -219,12 +219,12 @@ class MonitorPlugin(BasePlugin):
|
||||
|
||||
Args:
|
||||
provider: 提供商名称
|
||||
model: 模型名称
|
||||
model: 模型名称(保留签名兼容性,不再作为 Prometheus 标签)
|
||||
input_tokens: 输入token数
|
||||
output_tokens: 输出token数
|
||||
cost: 费用
|
||||
"""
|
||||
labels = {"provider": provider, "model": model}
|
||||
labels = {"provider": provider}
|
||||
|
||||
import asyncio
|
||||
|
||||
|
||||
@@ -74,21 +74,19 @@ class PrometheusPlugin(MonitorPlugin):
|
||||
http_label_names,
|
||||
)
|
||||
|
||||
# Token使用指标
|
||||
# Token使用指标(仅按 provider 维度聚合,避免 provider x model 笛卡尔积导致基数爆炸)
|
||||
self._metrics["tokens_input_total"] = Counter(
|
||||
"tokens_input_total", "Total input tokens", ["provider", "model"]
|
||||
"tokens_input_total", "Total input tokens", ["provider"]
|
||||
)
|
||||
|
||||
self._metrics["tokens_output_total"] = Counter(
|
||||
"tokens_output_total", "Total output tokens", ["provider", "model"]
|
||||
"tokens_output_total", "Total output tokens", ["provider"]
|
||||
)
|
||||
|
||||
self._metrics["tokens_total"] = Counter(
|
||||
"tokens_total", "Total tokens", ["provider", "model"]
|
||||
)
|
||||
self._metrics["tokens_total"] = Counter("tokens_total", "Total tokens", ["provider"])
|
||||
|
||||
self._metrics["usage_cost_total"] = Counter(
|
||||
"usage_cost_total", "Total usage cost in USD", ["provider", "model"]
|
||||
"usage_cost_total", "Total usage cost in USD", ["provider"]
|
||||
)
|
||||
|
||||
# 系统指标
|
||||
@@ -112,7 +110,7 @@ class PrometheusPlugin(MonitorPlugin):
|
||||
self._metrics["provider_latency_seconds"] = Histogram(
|
||||
"provider_latency_seconds",
|
||||
"Provider response latency in seconds",
|
||||
["provider", "model"],
|
||||
["provider"],
|
||||
buckets=(0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user