引言
Agent系统面临独特的流量挑战:LLM推理的QPS受GPU数量硬性限制、工具调用可能触发外部API限流、突发的复杂查询可能导致单请求消耗数十倍于平均值的资源。传统的固定阈值限流无法应对这些挑战,Agent系统需要更智能的限流和熔断机制。
2026年,自适应限流已成为Agent系统的标配——系统根据实时负载和资源利用率动态调整限流策略,在保护系统的同时最大化吞吐量。
Agent系统的流量特征
传统Web应用流量 Agent系统流量
│ │
│ ╱╲ │ ╱╲
│ ╱ ╲ ╱╲ │ ╱ ╲╱╲╱╲
│ ╱ ╲__╱ ╲___ │ ╱ ╲___
│________________ │________________
时间 时间
相对均匀的请求量 突发性强、长尾明显
每请求资源消耗相近 单请求资源消耗差异巨大(10-100x)
令牌桶限流
基础令牌桶
import asyncio
import time
from dataclasses import dataclass
@dataclass
class TokenBucket:
"""令牌桶限流器"""
capacity: float # 桶容量
refill_rate: float # 每秒补充令牌数
tokens: float = 0 # 当前令牌数
last_refill: float = 0 # 上次补充时间
def __post_init__(self):
self.tokens = self.capacity
self.last_refill = time.monotonic()
async def acquire(self, tokens: int = 1) -> bool:
"""获取令牌"""
while True:
self._refill()
if self.tokens >= tokens:
self.tokens -= tokens
return True
# 令牌不足,等待补充
wait_time = (tokens - self.tokens) / self.refill_rate
await asyncio.sleep(min(wait_time, 0.1))
def _refill(self):
"""补充令牌"""
now = time.monotonic()
elapsed = now - self.last_refill
self.tokens = min(
self.capacity,
self.tokens + elapsed * self.refill_rate
)
self.last_refill = now
def try_acquire(self, tokens: int = 1) -> bool:
"""非阻塞获取令牌"""
self._refill()
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
多维度限流
class AgentRateLimiter:
"""Agent多维度限流器"""
def __init__(self):
# 不同维度的限流器
self.limiters = {
"requests_per_minute": TokenBucket(capacity=100, refill_rate=100/60),
"tokens_per_minute": TokenBucket(capacity=50000, refill_rate=50000/60),
"tool_calls_per_minute": TokenBucket(capacity=50, refill_rate=50/60),
"concurrent_sessions": SemaphoreLimiter(max_concurrent=20),
"gpu_concurrent": SemaphoreLimiter(max_concurrent=4),
}
async def check_request(self, request: dict) -> dict:
"""检查请求是否被允许"""
required = {
"requests_per_minute": 1,
"concurrent_sessions": 1,
}
# 根据请求类型添加额外限制
if request.get("estimated_tokens"):
required["tokens_per_minute"] = request["estimated_tokens"]
if request.get("tool_calls"):
required["tool_calls_per_minute"] = len(request["tool_calls"])
if request.get("requires_gpu"):
required["gpu_concurrent"] = 1
# 检查所有维度
for dim, amount in required.items():
limiter = self.limiters[dim]
if not limiter.try_acquire(amount):
return {
"allowed": False,
"limited_dimension": dim,
"retry_after_ms": self._get_retry_after(dim, amount),
"message": f"Rate limit exceeded: {dim}"
}
return {"allowed": True}
def _get_retry_after(self, dimension: str, amount: int) -> int:
"""计算重试等待时间"""
limiter = self.limiters[dimension]
if hasattr(limiter, 'refill_rate'):
return int((amount - limiter.tokens) / limiter.refill_rate * 1000)
return 1000 # 默认1秒
自适应限流
class AdaptiveRateLimiter:
"""自适应限流器——基于系统负载动态调整"""
def __init__(self, config: dict):
self.min_limit = config.get("min_limit", 10)
self.max_limit = config.get("max_limit", 1000)
self.current_limit = config.get("initial_limit", 100)
# AIMD参数
self.additive_increase = config.get("additive_increase", 1)
self.multiplicative_decrease = config.get("multiplicative_decrease", 0.5)
# 系统指标
self.metrics = {
"cpu_utilization": 0,
"memory_utilization": 0,
"gpu_utilization": 0,
"p99_latency_ms": 0,
"error_rate": 0,
}
# 调整周期
self.adjustment_interval = 10 # 秒
self.window_requests = 0
self.window_errors = 0
async def should_allow(self, request: dict) -> bool:
"""判断是否允许请求"""
current_rps = self.window_requests / self.adjustment_interval
if current_rps >= self.current_limit:
return False
self.window_requests += 1
return True
async def adjust_limits(self):
"""定期调整限流阈值"""
while True:
await asyncio.sleep(self.adjustment_interval)
# 计算系统健康度
health_score = self._calculate_health()
if health_score > 0.8:
# 系统健康,增加限流(AIMD的AI)
self.current_limit = min(
self.current_limit + self.additive_increase,
self.max_limit
)
logger.info(
f"Increasing rate limit to {self.current_limit} "
f"(health: {health_score:.2f})"
)
elif health_score < 0.5:
# 系统不健康,减少限流(AIMD的MD)
self.current_limit = max(
int(self.current_limit * self.multiplicative_decrease),
self.min_limit
)
logger.warning(
f"Decreasing rate limit to {self.current_limit} "
f"(health: {health_score:.2f})"
)
# 重置窗口
self.window_requests = 0
self.window_errors = 0
def _calculate_health(self) -> float:
"""计算系统健康度(0-1)"""
weights = {
"cpu_utilization": 0.2,
"memory_utilization": 0.15,
"gpu_utilization": 0.25,
"p99_latency_ms": 0.25,
"error_rate": 0.15,
}
thresholds = {
"cpu_utilization": 0.8,
"memory_utilization": 0.85,
"gpu_utilization": 0.9,
"p99_latency_ms": 2000,
"error_rate": 0.05,
}
score = 1.0
for metric, weight in weights.items():
value = self.metrics[metric]
threshold = thresholds[metric]
ratio = value / threshold if threshold > 0 else 0
if ratio > 1:
# 超过阈值,扣分
score -= weight * min(ratio - 1, 1)
return max(0, score)
熔断器设计
class CircuitBreaker:
"""熔断器"""
class State:
CLOSED = "closed" # 正常工作
OPEN = "open" # 熔断,拒绝请求
HALF_OPEN = "half_open" # 半开,试探恢复
def __init__(
self,
failure_threshold: int = 10,
failure_rate_threshold: float = 0.5,
recovery_timeout: float = 30.0,
half_open_max_calls: int = 3
):
self.state = self.State.CLOSED
self.failure_threshold = failure_threshold
self.failure_rate_threshold = failure_rate_threshold
self.recovery_timeout = recovery_timeout
self.half_open_max_calls = half_open_max_calls
self.failure_count = 0
self.success_count = 0
self.total_count = 0
self.last_failure_time = None
self.half_open_calls = 0
async def call(self, func, *args, **kwargs):
"""通过熔断器调用函数"""
if self.state == self.State.OPEN:
if self._should_attempt_recovery():
self.state = self.State.HALF_OPEN
self.half_open_calls = 0
logger.info("Circuit breaker entering half-open state")
else:
raise CircuitBreakerOpenError(
f"Circuit breaker is open. "
f"Retry after {self._recovery_remaining():.0f}s"
)
if self.state == self.State.HALF_OPEN:
if self.half_open_calls >= self.half_open_max_calls:
raise CircuitBreakerOpenError(
"Half-open: max probe calls reached"
)
self.half_open_calls += 1
try:
result = await func(*args, **kwargs)
await self._on_success()
return result
except Exception as e:
await self._on_failure()
raise
async def _on_success(self):
self.success_count += 1
self.total_count += 1
if self.state == self.State.HALF_OPEN:
if self.half_open_calls >= self.half_open_max_calls:
self.state = self.State.CLOSED
self.failure_count = 0
logger.info("Circuit breaker recovered, closing")
async def _on_failure(self):
self.failure_count += 1
self.total_count += 1
self.last_failure_time = time.monotonic()
if self.state == self.State.HALF_OPEN:
self.state = self.State.OPEN
logger.warning("Circuit breaker re-opened from half-open")
elif self.state == self.State.CLOSED:
failure_rate = self.failure_count / max(self.total_count, 1)
if (self.failure_count >= self.failure_threshold or
failure_rate >= self.failure_rate_threshold):
self.state = self.State.OPEN
logger.error(
f"Circuit breaker opened: "
f"{self.failure_count}/{self.total_count} failures "
f"({failure_rate:.1%})"
)
多级熔断
class MultiLevelCircuitBreaker:
"""多级熔断器"""
def __init__(self):
self.breakers = {
"llm_inference": CircuitBreaker(
failure_threshold=5,
failure_rate_threshold=0.3,
recovery_timeout=30
),
"tool_search": CircuitBreaker(
failure_threshold=10,
failure_rate_threshold=0.5,
recovery_timeout=15
),
"vector_db": CircuitBreaker(
failure_threshold=8,
failure_rate_threshold=0.4,
recovery_timeout=10
),
"external_api": CircuitBreaker(
failure_threshold=3,
failure_rate_threshold=0.2,
recovery_timeout=60
),
}
async def call_with_fallback(
self,
primary: callable,
fallbacks: list,
circuit_key: str
):
"""带降级的熔断调用"""
breaker = self.breakers.get(circuit_key)
try:
if breaker:
return await breaker.call(primary)
return await primary()
except CircuitBreakerOpenError:
# 主路径熔断,尝试降级
for i, fallback in enumerate(fallbacks):
try:
logger.info(f"Trying fallback {i+1}/{len(fallbacks)}")
return await fallback()
except Exception as e:
logger.warning(f"Fallback {i+1} failed: {e}")
continue
# 所有降级都失败
raise AllFallbacksFailedError(
f"All fallbacks failed for {circuit_key}"
)
降级策略
class DegradationStrategy:
"""Agent降级策略"""
LEVELS = {
"normal": {
"model": "gpt-4o",
"max_tools": 10,
"max_context": 128000,
"streaming": True,
},
"degraded_1": {
"model": "gpt-4o-mini", # 降级到小模型
"max_tools": 5,
"max_context": 32000,
"streaming": True,
},
"degraded_2": {
"model": "gpt-4o-mini",
"max_tools": 2, # 仅保留核心工具
"max_context": 8000,
"streaming": False,
},
"emergency": {
"model": "cached-response", # 使用缓存或模板回复
"max_tools": 0,
"max_context": 1000,
"streaming": False,
}
}
def get_current_level(self, system_load: float) -> str:
"""根据系统负载获取降级级别"""
if system_load < 0.7:
return "normal"
elif system_load < 0.85:
return "degraded_1"
elif system_load < 0.95:
return "degraded_2"
else:
return "emergency"
总结
Agent系统的限流与熔断需要从三个层面协同工作:令牌桶实现精确的多维度限流,自适应算法根据系统健康度动态调整阈值,熔断器在故障时快速切断流量并支持降级恢复。关键是在系统保护和用户体验之间找到平衡——过度保护会浪费资源,保护不足会导致雪崩。
核心原则:限流是预防,熔断是保护,降级是兜底。三者协同构成Agent系统的流量安全网,缺一不可。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
