工程化01:模型API接入

从流式输出、超时控制、重试、幂等到降级,掌握生产环境下接入大模型API的关键工程实践。

字数 1506 阅读时长 ≈ 5 分钟 2026-7-18 2026-7-27
工程化01:模型API接入

把大模型 API 接入生产环境,不只是调用一个 HTTP 接口那么简单。需要处理流式输出、超时、重试、幂等、降级等一系列工程问题,确保服务稳定可靠。

流式输出处理

为什么需要流式

场景非流式问题流式优势
长文本生成用户等待时间长,体验差边生成边展示,减少感知延迟
大模型响应慢超时风险高渐进式呈现,用户有反馈
实时对话无法实时交互逐字输出,接近自然对话
内容审核无法中途拦截可实时过滤敏感内容

流式协议

协议说明适用场景
SSE (Server-Sent Events)单向流,服务端推送到客户端聊天、文本生成
WebSocket双向流,支持全双工通信实时协作、多人编辑
HTTP/2 Server PushHTTP/2 特性,服务器主动推送需要推送多种资源

SSE 实现示例

@GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chat(@RequestParam String prompt) {
    return webClient.post()
        .uri("https://api.openai.com/v1/chat/completions")
        .header("Authorization", "Bearer " + apiKey)
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue(Map.of(
            "model", "gpt-4o",
            "messages", List.of(Map.of("role", "user", "content", prompt)),
            "stream", true
        ))
        .retrieve()
        .bodyToFlux(String.class)
        .filter(line -> !line.isEmpty() && line.startsWith("data:"))
        .map(line -> line.substring(6))
        .filter(json -> !"[DONE]".equals(json))
        .map(this::parseDelta);
}

private String parseDelta(String json) {
    try {
        JsonNode node = objectMapper.readTree(json);
        JsonNode delta = node.get("choices").get(0).get("delta");
        return delta.has("content") ? delta.get("content").asText() : "";
    } catch (Exception e) {
        return "";
    }
}

超时控制

超时层次设计

层次超时时间说明
请求级超时10-30秒单个模型请求的最大等待时间
连接超时3-5秒建立 TCP 连接的超时时间
读取超时5-10秒读取响应数据的超时时间
总超时30-60秒包含重试的总超时时间
客户端超时5-15秒前端等待响应的超时时间

超时实现示例

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create()
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
            .responseTimeout(Duration.ofSeconds(10))
    ))
    .build();

// 请求级超时
webClient.post()
    .uri("https://api.openai.com/v1/chat/completions")
    .bodyValue(request)
    .retrieve()
    .bodyToMono(String.class)
    .timeout(Duration.ofSeconds(30));

超时处理策略

策略说明适用场景
返回默认结果超时后返回预设响应非关键功能、兜底场景
降级到小模型超时后切换到更快的小模型需要保证响应速度
异步重试超时后后台异步重试可接受延迟的批处理
拒绝服务返回错误码,让客户端重试高优先级场景

重试机制

重试策略

策略说明适用场景
固定间隔每次重试间隔相同简单场景
指数退避间隔指数增长API 限流场景
随机抖动间隔加入随机因子避免重试风暴
组合策略指数退避 + 随机抖动生产环境推荐

重试实现示例

Retry retry = Retry.backoff(3, Duration.ofSeconds(1))
    .jitter(0.5)
    .filter(e -> e instanceof WebClientResponseException && 
                 ((WebClientResponseException) e).getStatusCode().is5xxServerError());

webClient.post()
    .uri("https://api.openai.com/v1/chat/completions")
    .bodyValue(request)
    .retrieve()
    .bodyToMono(String.class)
    .retryWhen(retry);

重试注意事项

注意事项说明
幂等性确保重试不会产生副作用
重试次数设置合理的最大重试次数
退避间隔避免短时间内大量重试
熔断机制连续失败后停止重试
监控告警记录重试次数和原因

幂等性设计

为什么需要幂等

场景问题影响
网络抖动请求重复到达重复生成内容
重试机制自动重试导致重复请求重复扣费、重复创建
客户端重试用户刷新页面重复提交

幂等实现方案

方案说明适用场景
请求 ID客户端生成唯一 ID,服务端去重所有场景
操作类型只读操作天然幂等查询、列表
状态机基于状态转换实现幂等有状态操作
唯一约束数据库唯一索引创建操作

幂等实现示例

@PostMapping("/generate")
public Mono<ResponseEntity<GenerateResponse>> generate(
    @RequestHeader("X-Request-Id") String requestId,
    @RequestBody GenerateRequest request) {
    
    return idempotentService.checkAndLock(requestId)
        .flatMap(isFirst -> {
            if (!isFirst) {
                return idempotentService.getCachedResponse(requestId)
                    .map(ResponseEntity::ok);
            }
            return modelService.generate(request)
                .flatMap(response -> idempotentService.cacheResponse(requestId, response))
                .map(ResponseEntity::ok);
        });
}

降级策略

降级触发条件

条件说明触发方式
API 不可用模型服务宕机健康检查失败
响应超时请求超时次数超过阈值超时统计
错误率过高错误率超过阈值错误率监控
流量突增请求量超过系统容量限流触发
成本控制Token 消耗超过预算成本监控

降级方案

方案说明适用场景
返回缓存结果使用历史缓存响应非实时查询
返回默认结果返回预设的静态响应非关键功能
切换小模型降级到更快更便宜的模型需要保证响应
拒绝服务返回错误码高优先级场景
排队处理请求进入队列异步处理批处理场景

降级实现示例

public Mono<String> generateWithFallback(String prompt) {
    return modelService.generate(prompt)
        .onErrorResume(e -> {
            log.warn("Model API failed, falling back to cache: {}", e.getMessage());
            return cacheService.get(prompt);
        })
        .switchIfEmpty(Mono.just("抱歉,当前服务繁忙,请稍后重试"));
}

生产级 API 接入最佳实践

架构设计

客户端 → API网关 → 业务服务 → 模型服务客户端 → 大模型API
                ↓                  ↓
              缓存层            重试/熔断
                ↓                  ↓
              降级服务          监控告警

配置管理

配置项说明示例
API Key模型服务密钥从环境变量读取
超时时间各类超时配置通过配置中心管理
重试策略重试次数和间隔动态可配置
降级开关降级策略开关支持动态切换
限流阈值请求限流配置按时间窗口配置

安全措施

措施说明
API Key 管理使用密钥管理服务,定期轮换
请求签名防止请求篡改
IP 白名单限制访问来源
速率限制防止 API 滥用
数据加密传输和存储加密

常见问题与解决方案

问题1:流式输出中断

表现:客户端接收流时突然中断

解决方案

  • 设置合理的读取超时时间
  • 实现心跳机制
  • 添加重连逻辑
  • 记录中断原因

问题2:API 限流

表现:收到 429 Too Many Requests 错误

解决方案

  • 实现请求排队
  • 增加 API Key 池
  • 实现指数退避重试
  • 优化请求频率

问题3:Token 耗尽

表现:API 返回额度不足错误

解决方案

  • 监控 Token 使用量
  • 设置每日预算
  • 实现自动告警
  • 降级到免费模型

问题4:响应不稳定

表现:相同输入返回不同结果

解决方案

  • 设置固定的采样参数
  • 添加结果缓存
  • 实现结果一致性校验
  • 使用温度参数控制随机性

项目判断清单

  • 需要实时响应 → 使用流式输出
  • 请求可能超时 → 设置多级超时控制
  • API 可能失败 → 实现重试机制
  • 重复请求有副作用 → 设计幂等性方案
  • 需要保证可用性 → 实现降级策略
  • API 有调用限制 → 实现限流和排队
  • 成本敏感 → 监控 Token 使用量
  • 需要稳定响应 → 固定采样参数