共计 1787 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在分布式 AI 推理场景中,我们经常遇到以下问题:

- Token 分配不均 :Nginx 日志显示,30% 的 GPU 节点长期处于空闲状态,而 20% 的节点持续过载(P99 延迟 >2s)
- GPU 空转 :Prometheus 监控到平均 GPU 利用率仅为 35%,主要因请求到达不均衡导致 CUDA Context Switch 开销过大
- 请求堆积 :当突发流量达到平时 3 倍时,直接调用模式导致 50% 的请求因超时被丢弃
架构对比
我们对比了三种常见方案:
- 直接调用
- 吞吐量:1000 QPS(受限于单个节点性能)
- 延迟:P50=80ms,但 P99 高达 1200ms
-
成本:需要预留 50% 的冗余机器应对峰值
-
API 网关
- 吞吐量:3000 QPS(Nginx 层瓶颈)
- 延迟:增加 20ms 的代理开销
-
成本:需要专用网关服务器
-
中转站方案
- 吞吐量:8000 QPS(实测值)
- 延迟:P99 控制在 300ms 内
- 成本:利用现有消息队列基础设施
选型决策树:
- 如果 QPS<2000 → 直接调用
- 如果需要会话保持 → API 网关
- 如果追求资源利用率 → 中转站
核心实现
RabbitMQ 请求缓冲
import pika
from typing import Dict
class MQManager:
def __init__(self, host: str):
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=host)
)
self.channel = self.connection.channel()
self.channel.basic_qos(prefetch_count=100) # 关键参数!def declare_queue(self, queue_name: str) -> None:
self.channel.queue_declare(
queue=queue_name,
durable=True, # 持久化防止重启丢失
arguments={"x-max-priority": 10 # 支持优先级}
)
动态权重算法
def calculate_weight(gpu_stats: Dict) -> float:
""":param gpu_stats: {'mem_used': 1024, # MB'utilization': 0.65, # 0-1'temp': 75 # 摄氏度}
"""
# 归一化处理
mem_score = 1 - (gpu_stats['mem_used'] / 8192) # 假设 8G 显存
util_score = 1 - gpu_stats['utilization']
temp_score = max(0, 1 - (gpu_stats['temp'] / 85)) # 温度阈值 85℃
# 加权计算(可动态调整)return 0.5 * mem_score + 0.3 * util_score + 0.2 * temp_score
生产考量
熔断机制
采用 10 秒滑动窗口统计:
- 当错误率 >5% → 触发降级
- 连续 3 个窗口超阈值 → 彻底熔断
JWT 验证
import hmac
from hashlib import sha256
def verify_token(token: str, secret: bytes) -> bool:
try:
header, payload, signature = token.split('.')
expected = hmac.new(secret,
f"{header}.{payload}".encode(),
sha256).hexdigest()
return hmac.compare_digest(signature, expected)
except:
return False
避坑指南
- prefetch_count 优化 :建议值 = 平均处理时间 (ms)/100。例如处理耗时 200ms → prefetch_count=2
- 多 AZ 时间漂移 :所有节点强制使用 NTP 同步,并在 Token 中加入 ”issued_at” 时间戳(允许±3 秒误差)
开放性问题
当物理机与容器混合部署时,如何保证 Token 分配的公平性?可能的思路:
- 引入资源标签系统
- 按实际算力(而非简单轮询)分配
- 动态调整容器配额
这个方案在实际落地后,我们的 GPU 利用率从 35% 提升到了 82%,P99 延迟降低到 300ms 以内。特别要注意的是消息队列的积压监控,我们曾因 prefetch_count 设置不当导致内存溢出。建议在控制台实时显示队列深度,这是比监控面板更直观的预警方式。
正文完
发表至: 未分类
近两天内
