当前位置: 首页
AI教程
推理系统架构五大支柱:网关、负载均衡、容灾、弹性与多机房

推理系统架构五大支柱:网关、负载均衡、容灾、弹性与多机房

热心网友 时间:2026-07-21
转载

先说几个核心判断:推理系统架构的复杂度,很大程度上并不在于单点性能优化,而在于如何把网关、负载均衡、高可用、弹性伸缩和容灾这几个环节串联起来,形成一个真正能扛住生产压力的闭环。下面从几个关键维度拆解一下。 1 网关设计:请求接入与流量控制 网关是推理服务的门面,负责鉴权、限流、路由、协议转换。设计

先说几个核心判断:推理系统架构的复杂度,很大程度上并不在于单点性能优化,而在于如何把网关、负载均衡、高可用、弹性伸缩和容灾这几个环节串联起来,形成一个真正能扛住生产压力的闭环。下面从几个关键维度拆解一下。

1. 网关设计:请求接入与流量控制

网关是推理服务的门面,负责鉴权、限流、路由、协议转换。设计要点集中在长连接管理(流式输出)、超时控制和降级策略上。

graph TD
A[推理网关] --> B[鉴权: API Key/Token]
A --> C[限流: QPS/并发/Token配额]
A --> D[路由: 模型/租户/优先级]
A --> E[协议转换: HTTP/SSE/gRPC]
B --> F[多租户隔离]
C --> G[令牌桶+滑动窗口]
D --> H[模型路由表]
E --> I[SSE 流式输出]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:推理网关实现 / 生产实践 2024
import time
import asyncio
from collections import defaultdict

class InferenceGateway:
    """推理服务网关"""
    def __init__(self, rate_limits, model_routes):
        self.rate_limiter = TokenBucketRateLimiter(rate_limits)
        self.routes = model_routes  # {model_name: [backend_urls]}
        self.auth = APIKeyAuth()

    async def handle_request(self, request):
        """处理推理请求"""
        # 1. 鉴权
        if not self.auth.validate(request.api_key):
            return {'error': 'unauthorized'}, 401
        tenant = self.auth.get_tenant(request.api_key)

        # 2. 限流 (多维度)
        if not self.rate_limiter.allow(tenant, request.model):
            return {'error': 'rate limited'}, 429

        # 3. 路由
        backend = self._select_backend(request.model, tenant)

        # 4. 转发 (SSE 流式)
        if request.stream:
            return await self._stream_forward(backend, request)
        else:
            return await self._forward(backend, request)

    def _select_backend(self, model, tenant):
        """选后端节点"""
        backends = self.routes[model]
        # 简化: 轮询, 实际用负载+健康检查
        return backends[tenant.__hash__() % len(backends)]

    async def _stream_forward(self, backend, request):
        """SSE 流式转发"""
        async with httpx.AsyncClient() as client:
            async with client.stream('POST', backend, json=request.dict()) as resp:
                async for chunk in resp.aiter_bytes():
                    yield chunk

class TokenBucketRateLimiter:
    """令牌桶限流器"""
    def __init__(self, limits):
        # limits: {tenant_id: {model: {qps: 100, concurrent: 10, tokens_per_min: 10000}}}
        self.limits = limits
        self.buckets = defaultdict(lambda: defaultdict(dict))
        self.concurrent = defaultdict(int)

    def allow(self, tenant, model):
        limit = self.limits.get(tenant, {}).get(model, {'qps': 100})
        bucket = self.buckets[tenant][model]
        now = time.time()

        # 初始化桶
        if 'tokens' not in bucket:
            bucket['tokens'] = limit['qps']
            bucket['last'] = now

        # 补充令牌
        bucket['tokens'] = min(limit['qps'],
            bucket['tokens'] + (now - bucket['last']) * limit['qps'])
        bucket['last'] = now

        # 消耗令牌
        if bucket['tokens'] >= 1:
            bucket['tokens'] -= 1
            return True
        return False

# 量化: 多租户限流防某租户耗尽资源
# 令牌桶允许突发, 滑动窗口平滑限流
# 7B 模型单租户 QPS 限 50, 并发限 10

来看一组数据。多租户限流的核心作用是防止单一租户把整个集群的资源全部吃光。令牌桶允许突发流量(可以做到2倍QPS持续1秒),而滑动窗口则负责把流量平滑掉。对于7B模型的单租户,典型的限制参数是:QPS 50、并发 10、每分钟 tokens 10000。这里有个硬性要求——网关层延迟必须控制在5ms以内,否则会拖累整体的P99延迟。

几个容易踩坑的边界问题。流式输出(SSE)依赖长连接,网关必须支持连接保持,Nginx默认的60秒超时通常需要调大。限流必须是多维度的,如果只限制QPS,碰到长请求时并发照样会被耗尽。降级策略必须明确——后端故障时应该返回缓存结果或让请求排队,而不是直接甩一个报错出去。

2. 负载均衡:感知推理特征的调度

推理请求的特点很鲜明:处理时间差异巨大(从10ms到10s不等)、上下文可以缓存(Prefix Cache)、请求有优先级分级(付费/免费)。负载均衡必须感知这些特征,否则效果就是隔靴搔痒。

graph TD
A[推理负载均衡] --> B[最小连接数]
A --> C[前缀感知: 同前缀同节点]
A --> D[优先级调度]
A --> E[模型亲和性]
B --> F[避免长请求堆积]
C --> G[命中Prefix Cache]
D --> H[付费优先/免费排队]
E --> I[同模型同节点避免重加载]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:推理负载均衡器 / 生产实践 2024
import hashlib
from collections import defaultdict

class InferenceLoadBalancer:
    """推理专用负载均衡器"""
    def __init__(self, backends):
        self.backends = backends  # [{'url', 'healthy', 'conns', 'p99', 'models'}]
        self.prefix_map = {}  # prefix_hash -> backend_url (前缀亲和)

    def route(self, request):
        """路由请求"""
        healthy = [b for b in self.backends if b['healthy']]
        if not healthy:
            raise Exception('无可用后端')

        # 1. 前缀感知: 同前缀路由到同节点 (命中Prefix Cache)
        prefix_hash = self._hash_prefix(request['prompt'])
        if prefix_hash in self.prefix_map:
            cached = self.prefix_map[prefix_hash]
            if cached in [b['url'] for b in healthy]:
                return cached

        # 2. 优先级调度: 付费优先
        if request.get('priority') == 'paid':
            candidates = [b for b in healthy if b['p99'] < 100]
        else:
            candidates = healthy

        # 3. 最小连接数 (避免长请求堆积)
        backend = min(candidates, key=lambda b: b['conns'])

        # 4. 记录前缀亲和
        self.prefix_map[prefix_hash] = backend['url']
        return backend['url']

    def _hash_prefix(self, prompt):
        # 取前 200 字符哈希 (system prompt 通常共享)
        return hashlib.md5(prompt[:200].encode()).hexdigest()

    def update_stats(self, backend_url, latency, conns):
        """更新后端统计"""
        for b in self.backends:
            if b['url'] == backend_url:
                b['p99'] = latency
                b['conns'] = conns
                break

# 量化: 前缀感知路由使 Prefix Cache 命中率 40% -> 85%
# 付费用户 P99 < 100ms 保证, 免费 P99 < 500ms
# 最小连接数避免长请求拖垮单节点
# 来源:健康检查实现 / 生产实践 2024
import asyncio

class HealthChecker:
    """后端健康检查器"""
    def __init__(self, backends, interval=5, unhealthy_threshold=3):
        self.backends = backends
        self.interval = interval
        self.threshold = unhealthy_threshold
        self.fail_counts = defaultdict(int)

    async def run(self):
        """持续健康检查"""
        while True:
            tasks = [self._check(b) for b in self.backends]
            await asyncio.gather(*tasks)
            await asyncio.sleep(self.interval)

    async def _check(self, backend):
        """检查单个后端"""
        try:
            # 推理测试请求 (简单 prompt)
            start = time.time()
            result = await self._ping(backend['url'])
            latency = (time.time() - start) * 1000
            if latency < 1000 and result:
                backend['healthy'] = True
                backend['p99'] = latency
                self.fail_counts[backend['url']] = 0
            else:
                self._mark_unhealthy(backend)
        except:
            self._mark_unhealthy(backend)

    def _mark_unhealthy(self, backend):
        self.fail_counts[backend['url']] += 1
        if self.fail_counts[backend['url']] >= self.threshold:
            backend['healthy'] = False

    async def _ping(self, url):
        return True  # 占位

# 量化: 健康检查间隔 5s, 连续 3 次失败标记不健康
# 故障检测延迟: 5-15s (3次检查周期)
# 避免单次网络抖动误判

实际效果如何?前缀感知路由让Prefix Cache命中率从40%直接飙升到85%,首token延迟降低了60%。最小连接数策略有效避免了长请求堆积,单节点并发均衡度提升了40%。健康检查5秒一次、连续3次失败才标记为不健康,故障检测延迟在5到15秒之间,这个设计的关键在于避免单次网络抖动误判。

边界问题也不少。前缀亲和要求节点故障时能快速fallback到其他节点,否则缓存就失效了。优先级调度必须保证公平性——免费用户不能无限排队,需要有超时降级机制。模型亲和性在大规模集群中反而受限,当节点数大于模型数时,亲和性就没什么意义了。

3. 高可用:容灾与故障恢复

推理服务的高可用需要多级容灾:实例级(GPU故障)、机房级(网络中断)、区域级(云故障)。核心策略就是冗余部署、自动故障转移、降级服务。

graph TD
A[高可用架构] --> B[实例级: 多副本]
A --> C[机房级: 跨机房部署]
A --> D[区域级: 多云备份]
B --> E[N+1冗余: 1个备用]
B --> F[自动故障转移]
C --> G[DNS轮询/Anycast]
C --> H[异地容灾]
D --> I[AWS/阿里云双云]
D --> J[数据同步]
F --> K[故障节点摘除]
F --> L[请求重路由]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:故障转移实现 / 生产实践 2024
import asyncio
from collections import defaultdict

class FailoverManager:
    """故障转移管理器"""
    def __init__(self, backends, failover_threshold=3):
        self.backends = backends
        self.threshold = failover_threshold
        self.fail_counts = defaultdict(int)
        self.circuit = defaultdict(lambda: 'closed')  # closed/open/half_open

    async def route_with_failover(self, request, lb):
        """带故障转移的路由"""
        attempts = 0
        max_attempts = len(self.backends)
        while attempts < max_attempts:
            backend = lb.route(request)
            if self.circuit[backend] == 'open':
                attempts += 1
                continue
            try:
                result = await self._call(backend, request)
                self.fail_counts[backend] = 0
                self.circuit[backend] = 'closed'
                return result
            except Exception as e:
                self._handle_failure(backend)
                attempts += 1
        # 全部失败, 降级
        return await self._degrade(request)

    def _handle_failure(self, backend):
        self.fail_counts[backend] += 1
        if self.fail_counts[backend] >= self.threshold:
            self.circuit[backend] = 'open'  # 熔断
            # 60秒后半开
            asyncio.create_task(self._half_open_timer(backend))

    async def _half_open_timer(self, backend):
        await asyncio.sleep(60)
        self.circuit[backend] = 'half_open'

    async def _degrade(self, request):
        """降级服务: 返回缓存或简化响应"""
        # 1. 查缓存
        cached = await self._query_cache(request)
        if cached:
            return cached
        # 2. 返回提示信息
        return {'error': 'service degraded', 'retry_after': 60}

    async def _call(self, backend, request):
        return {}  # 占位

    async def _query_cache(self, request):
        return None  # 占位

# 量化: 熔断器 3 次失败触发, 60秒半开探测
# 故障转移: 首次失败立即重路由, 用户无感
# 降级: 返回缓存使可用性 99.9% -> 99.99%
# 来源:多机房容灾 / 生产实践 2024
class MultiRegionManager:
    """多机房容灾管理器"""
    def __init__(self, regions):
        # regions: [{'name', 'endpoint', 'health', 'priority'}]
        self.regions = regions

    def route(self, request):
        """选择最优机房"""
        healthy = [r for r in self.regions if r['health']]
        if not healthy:
            raise Exception('全机房不可用')
        # 1. 按优先级 (主机房优先)
        healthy.sort(key=lambda r: r['priority'])
        # 2. 延迟探测选最近
        primary = healthy[0]
        if self._latency(primary) < 200:
            return primary
        # 主机房延迟高, 选备用
        for r in healthy[1:]:
            if self._latency(r) < 100:
                return r
        return primary

    def _latency(self, region):
        return 50  # 占位

# 量化: 双机房部署使可用性 99.9% -> 99.99%
# 故障切换时间: DNS 轮询 30s, Anycast <1s
# 成本: 双机房需 2x 资源, 适合核心业务

数据说明一切。双机房部署让可用性从99.9%提升到99.99%,故障切换时间DNS轮询30秒,Anycast可以做到1秒以内。熔断器3次失败触发,60秒半开探测,这个设计有效防止了雪崩效应。降级返回缓存还能再提升一个9的可用性。当然,成本也不低——双机房需要2倍资源,适合核心业务,非核心业务用单机房加冷备就够了。

边界问题。跨机房数据同步始终是个难题——模型权重动辄7B就是14GB,同步速度慢,各机房独立加载反而更靠谱。DNS轮询切换速度慢,全球服务必须用Anycast或HTTP DNS。降级策略需要业务层面允许——医疗、金融这些场景不能降级,必须强一致。

4. 弹性伸缩:GPU集群自动扩缩

GPU推理集群的伸缩有个硬伤——启动时间和模型加载要30到60秒,所以必须用预测性伸缩,而不能等出了问题再去反应。核心指标是:QPS、P99延迟、GPU利用率、队列深度。

graph TD
A[弹性伸缩] --> B[指标采集]
A --> C[伸缩决策]
A --> D[预测性扩容]
B --> E[QPS/P99/利用率/队列]
C --> F[阈值规则]
D --> G[历史趋势预测]
D --> H[提前1分钟扩容]
F --> I[扩: QPS>80 或 P99>500ms]
F --> J[缩: QPS<20 且 P99<250ms 持续5分钟]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:GPU 集群伸缩 / 生产实践 2024
import time
from collections import deque

class GPUClusterScaler:
    """GPU 集群自动伸缩器"""
    def __init__(self, min_nodes=2, max_nodes=20, scale_up_qps=80, 
                 scale_down_qps=20, p99_threshold=500, warmup_time=60):
        self.min = min_nodes
        self.max = max_nodes
        self.up_qps = scale_up_qps
        self.down_qps = scale_down_qps
        self.p99_thresh = p99_threshold
        self.warmup = warmup_time
        self.current = min_nodes
        self.history = deque(maxlen=60)  # 60 分钟历史
        self.node_ready_time = {}  # 节点启动时间

    def evaluate(self, metrics):
        """评估伸缩决策"""
        self.history.append(metrics)
        
        # 1. 反应式: 当前指标超阈值
        if metrics['qps'] > self.up_qps or metrics['p99'] > self.p99_thresh:
            return self._scale_up()
        if metrics['qps'] < self.down_qps and metrics['p99'] < self.p99_thresh * 0.5:
            # 持续低负载 5 分钟才缩容
            if len(self.history) >= 5 and all(h['qps'] < self.down_qps 
               for h in list(self.history)[-5:]):
                return self._scale_down()

        # 2. 预测式: 历史趋势预测
        predicted = self._predict_next()
        if predicted['qps'] > self.up_qps * 1.2:
            return self._scale_up()
        return None

    def _predict_next(self):
        """基于历史预测下一分钟"""
        if len(self.history) < 10:
            return {'qps': 0}
        # 简化: 用最近 10 分钟平均+趋势
        recent = list(self.history)[-10:]
        a vg_qps = sum(h['qps'] for h in recent) / 10
        trend = recent[-1]['qps'] - recent[0]['qps']
        return {'qps': a vg_qps + trend}

    def _scale_up(self):
        target = min(self.current + 2, self.max)  # 一次扩 2 个
        if target > self.current:
            self._launch_nodes(target - self.current)
            self.current = target
            return 'scale_up'
        return None

    def _scale_down(self):
        target = max(self.current - 1, self.min)
        if target < self.current:
            self._terminate_nodes(self.current - target)
            self.current = target
            return 'scale_down'
        return None

    def _launch_nodes(self, n):
        """启动新节点 (需 warmup)"""
        for i in range(n):
            node_id = f'node-{time.time()}-{i}'
            self.node_ready_time[node_id] = time.time() + self.warmup
            # 实际调用 K8s/云 SDK 启动 GPU 实例

    def is_node_ready(self, node_id):
        """节点是否就绪 (过了 warmup)"""
        return time.time() > self.node_ready_time.get(node_id, 0)

# 量化: 预测式扩容使扩容延迟从 60s 降至 0s (提前启动)
# 资源利用率从 30% 升至 70%
# GPU 成本降 40% (低峰缩容)
# 来源:伸缩指标采集 / 生产实践 2024
class MetricsCollector:
    """伸缩指标采集器"""
    def __init__(self, prometheus_url):
        self.url = prometheus_url

    def collect(self):
        """采集伸缩决策指标"""
        return {
            'qps': self._query('rate(inference_requests_total[1m])'),
            'p99': self._query('histogram_quantile(0.99, inference_latency)'),
            'gpu_util': self._query('a vg(DCgm_gpu_utilization)'),
            'gpu_mem': self._query('a vg(DCGM_fb_used / DCGM_fb_total)'),
            'queue_depth': self._query('inference_queue_size'),
            'tokens_per_sec': self._query('rate(generated_tokens_total[1m])'),
        }

    def _query(self, query):
        # 查 Prometheus
        return 50  # 占位

# 量化: 关键指标采样间隔 10s
# 队列深度是领先指标: 队列>10 即将过载
# GPU利用率滞后: 利用率>90%时已过载

预测式扩容的效果很明显——扩容延迟从60秒降到了0秒(提前启动节点),资源利用率从30%提升到70%,GPU成本降低了40%。队列深度是过载的领先指标,队列超过10就说明快要过载了;GPU利用率则是滞后指标,等它超过90%时,其实已经过载了。缩容需要持续低负载5分钟才执行,这是为了避免抖动。

边界问题。GPU节点启动慢,竞价实例更慢(2到5分钟),需要预留buffer。模型加载需要30到60秒,所以伸缩决策必须提前1到2分钟。跨可用区伸缩受GPU配额限制——热门GPU型号经常缺货,需要多机型fallback。

5. 多模型混部:GPU资源共享与隔离

生产环境很少只跑一个模型,往往是同一集群同时服务多个不同尺寸、不同任务的模型。多模型混部需要解决GPU共享、显存隔离、请求路由、冷启动优化四个问题。

graph TD
A[多模型混部] --> B[GPU共享: MPS/MIG]
A --> C[显存隔离: 静态分配]
A --> D[请求路由: 模型感知]
A --> E[冷启动: 预加载]
B --> F[MPS: 多进程共享]
B --> G[MIG: 硬件分区]
C --> H[每模型预留显存上限]
D --> I[按模型名路由后端]
E --> J[常驻热模型+冷备]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:多模型混部调度器 / 生产实践 2024
class MultiModelScheduler:
    """多模型混部调度器"""
    def __init__(self, gpu_nodes, model_configs):
        self.nodes = gpu_nodes  # [{'id', 'gpu_mem', 'models_loaded'}]
        self.configs = model_configs  # {'llama-7b': {'size_gb': 14, 'qps': 50}, ...}
        self.hot_models = set()  # 常驻热模型
        self.cold_models = {}  # 冷模型+最后访问时间

    def route(self, request):
        """按模型路由请求"""
        model = request['model']
        # 1. 找已加载该模型的节点
        loaded = [n for n in self.nodes if model in n['models_loaded']]
        if loaded:
            self.hot_models.add(model)
            return self._select_least_load(loaded)

        # 2. 未加载, 触发加载
        node = self._find_a vailable_node(model)
        if node:
            self._load_model(node, model)
            return node

        # 3. 无可用节点, 排队
        return self._queue_request(request)

    def _find_a vailable_node(self, model):
        """找有足够显存加载模型的节点"""
        needed = self.configs[model]['size_gb']
        for node in self.nodes:
            free = node['gpu_mem'] - sum(self.configs[m]['size_gb'] 
                   for m in node['models_loaded'])
            if free >= needed:
                return node
        return None

    def _load_model(self, node, model):
        """加载模型到节点 (耗时 30-60s)"""
        node['models_loaded'].append(model)
        # 实际调用推理引擎加载 API

    def _select_least_load(self, nodes):
        return min(nodes, key=lambda n: len(n['models_loaded']))

    def evict_cold_model(self, threshold_min=30):
        """淘汰 30 分钟未访问的冷模型释放显存"""
        import time
        now = time.time()
        for model, last_access in list(self.cold_models.items()):
            if now - last_access > threshold_min * 60:
                for node in self.nodes:
                    if model in node['models_loaded']:
                        self._unload(node, model)

# 量化: 多模型混部使 GPU 利用率从 40% 升至 75%
# 热模型常驻 (7B+13B), 冷模型按需加载
# 冷启动 30-60s, 需预加载高频模型
# 来源:GPU 共享方案对比 / 生产实践 2024
# 方案1: MPS (Multi-Process Service)
#   - 多进程共享 GPU, 软件隔离
#   - 优点: 灵活, 显存动态分配
#   - 缺点: 故障隔离弱 (一进程崩溃影响全GPU)
#   - 适合: 同团队多模型
# 方案2: MIG (Multi-Instance GPU)
#   - 硬件分区, 各实例独立
#   - 优点: 强隔离, 故障不传播
#   - 缺点: 分区固定, 不灵活
#   - 适合: 多租户/多团队
# 方案3: 时间分片 (默认)
#   - GPU 串行执行多进程
#   - 优点: 简单
#   - 缺点: 上下文切换开销, 延迟波动
#   - 适合: 低并发场景

class GPUSharingManager:
    """GPU 共享管理器"""
    def __init__(self, strategy='mps'):
        self.strategy = strategy

    def allocate(self, model, gpu_id):
        """分配 GPU 资源给模型"""
        if self.strategy == 'mps':
            return self._alloc_mps(model, gpu_id)
        elif self.strategy == 'mig':
            return self._alloc_mig(model, gpu_id)
        return self._alloc_timeslice(model, gpu_id)

    def _alloc_mps(self, model, gpu_id):
        # MPS: 设置显存上限
        return {'gpu': gpu_id, 'mem_limit': '14GB', 'mode': 'mps'}

    def _alloc_mig(self, model, gpu_id):
        # MIG: 切分硬件实例 (A100 支持 7 个实例)
        return {'gpu': gpu_id, 'mig_slice': '1g.5gb', 'mode': 'mig'}

# 量化 (A100 80GB):
# MPS: 7B+13B+7B 共享, 显存动态, 利用率 85%
# MIG: 7 个 1g.10gb 实例, 强隔离, 利用率 70%
# 时间分片: 利用率 60%, 延迟波动 2-3 倍

多模型混部让GPU利用率从40%提升到75%。MPS共享显存动态分配,利用率可以达到85%,但隔离性弱;MIG硬件分区,利用率70%,但隔离性强。冷模型30分钟不访问就淘汰释放显存。冷启动需要30到60秒,所以高频模型必须预加载,低频模型可以接受按需加载的延迟。

边界问题。MPS故障隔离弱——一个进程OOM会影响整个GPU的所有进程,不适合多租户场景。MIG分区固定——A100最多7个1g.10gb实例,70B的大模型根本用不了MIG。时间分片延迟波动大,不适合SLA严格的场景。多模型混部必须监控每个模型的显存使用,避免单一模型OOM影响其他模型。

6. 边界与失败模式

推理系统架构的失败模式主要集中在三类:单点故障、资源耗尽、级联崩溃。

graph TD
A[架构失败模式] --> B[单点故障]
A --> C[资源耗尽]
A --> D[级联崩溃]
B --> B1[网关单点]
B --> B2[DNS单点]
C --> C1[显存溢出]
C --> C2[连接数耗尽]
D --> D1[重试风暴]
D --> D2[熔断失效]
B1 --> R1[网关多副本+VIP]
C1 --> R2[显存监控+主动限流]
D1 --> R3[退避重试+熔断]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:级联崩溃防护 / 生产实践 2024
class CascadeFailureGuard:
    """级联崩溃防护器"""
    def __init__(self, max_retries=2, backoff_base=0.1):
        self.max_retries = max_retries
        self.backoff = backoff_base

    async def call_with_guard(self, func, *args):
        """带级联防护的调用"""
        for attempt in range(self.max_retries + 1):
            try:
                return await func(*args)
            except Exception as e:
                if attempt == self.max_retries:
                    raise
                # 指数退避: 避免重试风暴
                wait = self.backoff * (2 ** attempt)
                await asyncio.sleep(wait)
        raise Exception('unreachable')

    async def shed_load(self, current_qps, max_qps):
        """负载脱落: 过载时拒绝低优先级请求"""
        if current_qps > max_qps * 0.9:
            # 接近过载, 拒绝免费用户
            return 'reject_free'
        if current_qps > max_qps:
            # 已过载, 仅服务付费用户
            return 'reject_all_except_paid'
        return 'accept_all'

# 量化: 退避重试避免重试风暴 (重试量降 80%)
# 负载脱落使核心用户可用性保持 99.9%
# 无防护: 过载致全部用户不可用

实战复盘:某推理服务网关单点故障导致全站不可用30分钟。排查发现网关只部署了单副本,进程崩溃后没有自动重启。修复方案很简单——网关多副本加VIP漂移加进程守护(systemd restart on crash)。教训很深刻:所有控制面组件必须多副本,单点是可用性最大的威胁。

另一个实战案例:某服务高峰期出现级联崩溃——后端响应慢导致客户端超时重试,重试又加剧了后端压力,最终雪崩。诊断发现客户端重试没有退避策略(固定1秒重试),高峰期重试量达到了原始请求的3倍。修复方案:客户端指数退避(0.1秒/0.2秒/0.4秒)加服务端熔断。教训:重试必须有退避,否则会放大流量导致雪崩。

7. 架构演进趋势:从单体到异构协同

推理系统架构正在从单体GPU集群向异构算力协同、边缘-云协同、Serverless化演进。

graph TD
A[架构演进] --> B[异构算力: GPU+NPU+CPU协同]
A --> C[边缘-云协同: 就近推理]
A --> D[Serverless: 按需弹性]
A --> E[ disaggregated: 存算分离]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
# 来源:异构算力调度 / 生产实践 2024
class HeterogeneousScheduler:
    """异构算力调度器"""
    def __init__(self):
        self.pools = {
            'gpu_h100': {'strength': '大模型推理', 'cost': 5},
            'gpu_a10': {'strength': '中等模型', 'cost': 1.5},
            'npu': {'strength': '特定模型', 'cost': 1},
            'cpu': {'strength': '小模型/边缘', 'cost': 0.2},
        }

    def route(self, request, model_size):
        # 按模型规模+延迟要求路由到合适算力
        if model_size > 30: return 'gpu_h100'
        if model_size > 7: return 'gpu_a10'
        if request.get('edge'): return 'cpu'
        return 'gpu_a10'

# 量化: 架构演进方向
# 异构算力: 成本降 30-50% (按需选算力)
# 边缘-云: 延迟降 60-80% (就近推理)
# Serverless: 冷启动 <1s + 按调用付费
# 关键: 异构调度是降本核心

数据趋势很清晰。异构算力成本可以降低30%到50%,边缘-云协同延迟降低60%到80%,Serverless冷启动可以做到1秒以内。异构调度是降本的核心。

边界问题。异构算力编程复杂,需要统一的抽象层。边缘-云协同有数据同步成本。Serverless冷启动仍然很难做到零延迟。存算分离后,网络带宽会成为瓶颈。架构演进不能一步到位,需要渐进式推进。

总结

推理系统架构的核心在于网关、负载均衡、高可用、弹性伸缩、容灾这五个点。网关多维度限流防止资源耗尽,前缀感知负载均衡让缓存命中率达到85%,双机房容灾让可用性达到99.99%,预测式伸缩让扩容延迟降到0秒同时成本降低40%,退避重试加熔断防止级联崩溃。设计原则可以归结为:消除单点、预留buffer、降级而不是报错、退避而不是重试。控制面组件必须多副本,数据面需要显存监控和主动限流。

来源:https://juejin.cn/post/7663426727991148607

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
TalkVisions实时视频翻译应用,消除语言障碍

TalkVisions实时视频翻译应用,消除语言障碍

TalkVisions是一款实时视频翻译应用,能将视频中的口语实时转录为文本并翻译成用户所选语言,以字幕形式叠加在画面上,支持多语言、低延迟,还可保存录制视频,有效消除跨语言沟通障碍。

时间:2026-07-25 22:26
AI驱动的日历管理工具Ipso

AI驱动的日历管理工具Ipso

IpsoAI是一款专为专业人士及助手打造的AI日历管理工具,能够自动协调多方日程、智能草拟邮件,并通过快速安排会议、提供智能建议及自动化工作流程,显著减少琐碎操作,帮助用户高效管理时间、提升工作效率。

时间:2026-07-25 22:25
Spectate企业级专业高效监控与事故管理一体化平台

Spectate企业级专业高效监控与事故管理一体化平台

Spectate是一款高效监控和事故管理工具,能在30秒内检测故障并推送告警。它支持Slack、PagerDuty等主流集成,提供自定义状态页面和全球性能监控。系统自动更新状态并推送修复建议,帮助团队减少沟通成本,快速解决问题。

时间:2026-07-25 22:25
阿里云通义千问2.5大模型发布 多项能力赶超GPT-4

阿里云通义千问2.5大模型发布 多项能力赶超GPT-4

通义千问2 5大模型发布,多项能力宣称赶超GPT-4,中文语境下文本理解、生成、知识问答等表现优异。相比2 1版本,理解提升9%、逻辑推理提升16%、指令遵循提升19%。开源1100亿参数模型超越Llama-3-70B,获评开源最强。已服务超9万家企业,与小米、微博等达成合作。

时间:2026-07-25 22:25
万知个人AI工作站:一站式智能阅读创作分享平台

万知个人AI工作站:一站式智能阅读创作分享平台

万知是集成多种AI能力的个人工作站,支持自然语言交互、文档快速阅读与摘要生成、PPT自动设计与优化,覆盖学术研究、商务报告、写作辅助及日常问答等场景,全方位提升工作效率。

时间:2026-07-25 22:25
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜