云原生交付服务异常时如何分层降级
推理服务出现排队、显存不足或网关超时时,先把流量和故障域隔开。降级不是简单换模型:需要区分可排队请求、可返回缓存的请求,以及应直接提示稍后重试的请求。
现场故障与网关超时:GPU 显存溢出引发的 504 连锁响应。
排查故障第一步是通过标准命令行提取真实的现场诊断指标。利用命令行抓取 Pod 事件与 GPU 占用参数:
kubectl get pods -n llm-prod -l app=vllm-inference -o wide kubectl exec -it -n llm-prod vllm-inference-6789b5894-q9k2x -- nvidia-smi --query-gpu=timestamp,name,memory.used,memory.total,utilization.gpu --format=csv -l 1 curl -s -o /dev/null -w "HTTPStatus: %{http_code} | TotalTime: %{time_total}s\n" -X POST http://gateway.internal/v1/chat/completions -H "Content-Type: application/json" -d '{"model":"llama3-70b","prompt":"ping"}'控制台捕获到的响应结果呈现明显的资源瓶颈:
HTTPStatus: 504 | TotalTime: 15.002s GPU Timestamp, name, memory.used [MiB], memory.total [MiB], utilization.gpu [%] 2026-08-31 02:30:11, NVIDIA A100-SXM4-80GB, 81500 MiB, 81920 MiB, 100 %显存已无可分配空间,推理线程在等待 Cuda Malloc 释放空间,而上游请求仍在持续涌入。
自动降级架构设计:基于 Envoy 动态路由与规则断路器。
面对大模型推理过程中的延迟抖动,降级方案不能依赖人工登录集群手动修改 Service Label,应由 Sidecar 代理层或 API 网关层实现秒级自动切流。
路由规则通常分为三级治理策略:优先路由至 70B 主模型;一旦主模型连续 3 次响应超时或返回 50x 错误,自动触发熔断并降级至 8B 备用轻量模型;若备用模型也处于高负载状态,直接返回带有语义兜底提示的静态 JSON 响应。
规则引擎落地:用 Go 编写轻量级模型降级控制器。
在 Sidecar 或网关层注入轻量级 Proxy 逻辑,用于实时探测下游 vLLM 实例的服务状态。当错误率到达预设阈值时,自动修改内存中的 upstream 目标地址,实现无感知服务降级。
package downgrade import ( "context" "fmt" "net/http" "net/http/httputil" "net/url" "sync/atomic" "time" ) type ModelProxy struct { primaryURL *url.URL fallbackURL *url.URL failureCount int64 threshold int64 isDowngraded int32 } func NewModelProxy(primary, fallback string, failureThreshold int64) (*ModelProxy, error) { pURL, err := url.Parse(primary) if err != nil { return nil, fmt.Errorf("invalid primary url: %w", err) } fURL, err := url.Parse(fallback) if err != nil { return nil, fmt.Errorf("invalid fallback url: %w", err) } return &ModelProxy{ primaryURL: pURL, fallbackURL: fURL, threshold: failureThreshold, isDowngraded: 0, }, nil } func (p *ModelProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { downgraded := atomic.LoadInt32(&p.isDowngraded) == 1 targetURL := p.primaryURL if downgraded { targetURL = p.fallbackURL r.Header.Set("X-Model-Downgraded", "true") } proxy := httputil.NewSingleHostReverseProxy(targetURL) proxy.Transport = &http.Transport{ ResponseHeaderTimeout: 3 * time.Second, } proxy.ErrorHandler = func(rw http.ResponseWriter, req *http.Request, err error) { if !downgraded { failures := atomic.AddInt64(&p.failureCount, 1) if failures >= p.threshold { atomic.StoreInt32(&p.isDowngraded, 1) // 开启异步探活恢复协程 go p.recoverHealthCheck() } } rw.Header().Set("Content-Type", "application/json") rw.WriteHeader(http.StatusServiceUnavailable) _, _ = rw.Write([]byte(`{"error":{"code":"service_downgraded","message":"Primary model overloaded, fallback active."}}`)) } proxy.ServeHTTP(w, r) } func (p *ModelProxy) recoverHealthCheck() { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop() for range ticker.C { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) req, _ := http.NewRequestWithContext(ctx, "GET", p.primaryURL.String()+"/health", nil) resp, err := http.DefaultClient.Do(req) cancel() if err == nil && resp.StatusCode == http.StatusOK { atomic.StoreInt32(&p.isDowngraded, 0) atomic.StoreInt64(&p.failureCount, 0) return } } }代码实现的核心在于通过atomic保证多协程并发请求下的无锁切流效率。将ResponseHeaderTimeout限制在 3 秒以内,避免下游 GPU 卡死拖垮代理层的连接池。
故障复盘与诊断:通过 nvidia-smi 与 curl 验证降级逻辑。
代码部署上线前,应在测试环境中注入超时故障进行闭环验证。利用测试脚本模拟高压请求并打满 GPU 显存,观测 Proxy 的响应 Header 与切流动作:
# 模拟并发高压请求 hey -z 20s -c 40 -m POST -H "Content-Type: application/json" -d '{"prompt":"Generate long context string..."}' http://localhost:8080/v1/chat/completions # 实时监测降级 Header curl -i -X POST http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{"prompt":"test"}' | grep -E "(HTTP/|X-Model-Downgraded)"返回的诊断日志确认流量已顺畅切换:
HTTP/1.1 200 OK X-Model-Downgraded: true原本可能导致系统响应挂起的延迟,被控制在 3 秒以内并自动降级为备用节点的响应。
降级落地防坑指南:避免死锁与配置生效延迟的硬核对策。
生产环境落地时需要针对以下关键细节进行防护:
首先,降级后的 8B 小模型节点若承接全部流量,可能因资源过载触发二次故障。因此应在降级节点前严格配置 Rate Limiter 限制总 QPS。
其次,探活机制(Health Check)过于频繁可能导致刚恢复的主节点再次被突发流量冲垮。工程实践中应引入退避探活机制,并在切回主节点时采用阶梯式流量恢复策略(如按 10%、30%、按检查结果确认 逐步放行)。
将降级断路器逻辑配置于 Helm 的 ConfigMap,并结合 Kubernetes 的 Readiness Probe 动态探针,能够保障在 GPU 显存碎片化或模型推断卡死时,线上业务仍然可以平稳过渡。