Java SDK开发方法详解(AI 网关 SDK 完整实战)

一个可对外交付的 Java SDK,核心不在于能调通接口,而在于六个设计决策是否到位:配置驱动、统一数据模型、鉴权收敛、HTTP 客户端选型、异常分层、高可用治理。我在企业级 AI 网关的 SDK 开发中把这六块逐一定型,调用方拿到的是”配置即用”的体验——填一个网关地址和密钥,就能以方法调用的方式发起对话并接收 SSE 流,鉴权、重试、超时全部由 SDK 内部消化。

一、SDK 的定位与设计原则

SDK 是网关能力的语言侧封装,不是业务逻辑的搬运工。它只做四件事:组装请求、签名鉴权、传输、把响应翻译成类型化结果。原则有三条:配置驱动,密钥与端点不写死在代码里;协议集中,鉴权、错误码映射只实现一次;调用方零负担,不暴露内部线程与连接细节。

这条边界决定了很多取舍。把日志、限流、重试这类横切逻辑都塞进 SDK 是常见失控点——SDK 只负责一次调用的稳定性,全局治理交给网关层。同时 SDK 要区分”库”与”服务”:它只是一个被引入的 jar,不能假设自己运行在容器里,所以不持有线程池状态、不依赖 Spring 上下文之外的运行时环境,纯配置驱动,任何 Spring Boot 应用都能直接装配。

二、配置驱动

所有可变项收敛到一个配置类,用 Spring Boot 的绑定能力自动填充:

@ConfigurationProperties(prefix = "ai.gateway")
public class AiGatewayProperties {
    private String baseUrl;
    private String apiKey;
    private Duration connectTimeout = Duration.ofSeconds(5);
    private Duration readTimeout = Duration.ofSeconds(60);
    private int maxRetries = 2;
    // getter / setter 省略
}

配置项集中在 application.yml 里,调用方不用翻源码就能调整超时与重试。用配置类而不是到处写 @Value,还有个好处:SDK 提供默认值,调用方不配也能跑通默认链路,配了则精确覆盖,边界行为明确。

ai:
  gateway:
    base-url: https://ai-gateway.example.com
    api-key: ${AI_GATEWAY_KEY}
    read-timeout: 90s
    max-retries: 2

三、统一数据模型

请求与响应用 Java 17 的 record 定义,字段即契约。统一响应包裹结果、错误码与耗时,错误码透传网关侧定义,方便调用方对齐语义。

public record ChatRequest(String model, String prompt, boolean stream) {}
public record ChatResponse(String content, String requestId) {}
public record ApiResult<T>(int code, String message, T data) {}

模型名这类枚举值做成常量类暴露给调用方,避免字符串散落各处写错拼写。新增能力时先加模型类与端点常量,再补业务方法,契约演进受控。

四、鉴权收敛进拦截器

签名逻辑不能散落在每个业务方法里。网关侧采用 API Key + 时间戳签名,SDK 用 RestClient 拦截器统一注入请求头,业务方法只关心参数。

public class AuthInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        String ts = String.valueOf(System.currentTimeMillis());
        String sign = HmacSHA256.sign(ts + request.getURI().getPath(), apiKey);
        request.getHeaders().set("X-Api-Key", apiKey);
        request.getHeaders().set("X-Timestamp", ts);
        request.getHeaders().set("X-Sign", sign);
        return execution.execute(request, body);
    }
}

密钥只出现在配置与拦截器两处,审计和轮换都方便。

五、HTTP 客户端选型与流式调用

5.1 三种客户端怎么选

客户端 声明方式 适合场景 流式支持
RestTemplate 过程式 遗留代码 弱
OpenFeign 接口注解 契约稳定的服务间调用 一般
RestClient 流式 Builder 新代码、策略多变的外部调用 原生支持

SDK 面向外部网关、端点数量有限、鉴权与错误处理逐调用略有差异,选 RestClient 最合适,它是 Spring 官方推荐的新客户端,支持拦截器与按状态码处理错误。

5.2 构建客户端并支持 SSE

RestClient client = RestClient.builder()
    .baseUrl(props.getBaseUrl())
    .requestInterceptor(new AuthInterceptor(props))
    .requestFactory(JdkClientHttpRequestFactory.builder()
        .readTimeout(props.getReadTimeout())
        .build())
    .build();

流式对话返回 Flux,SDK 对调用方隐藏协议细节:

public Flux<String> streamChat(ChatRequest request) {
    return client.post()
        .uri("/v1/chat/completions")
        .body(request)
        .retrieve()
        .body(Flux<String>.class)
        .doOnError(e -> log.warn("stream error: {}", e.getMessage()));
}

SSE 流需要单独的路由与读取策略:连接建立后响应体不断返回,RestClient 基于响应式流按块读取,readTimeout 按首字节到达时间计算,而不是整体响应时间,否则长文本生成必然误报超时。

六、异常分层与高可用治理

异常体系要能区分错误来源,调用方才能对症处理。SDK 至少拆四类:网络与超时异常、鉴权异常、限流异常(对应 429)、网关业务异常(透传错误码)。全部继承同一个根异常,用 since 语义捕获一类即可。

治理在 SDK 内用 Resilience4j 落地,核心四条:重试只针对网络抖动类错误,配上退避,且请求带幂等键防止重复消费;熔断器在网关连续失败时快速失败,不再把请求打进去;并发信号量隔离单个模型的慢请求;超时用 readTimeout 兜底,避免调用方线程被耗尽。这四件套装完,SDK 在厂商侧抖动时依然稳得住。

异常翻译放在统一出口:客户端拿到的是结构化错误码而不是裸堆栈,429 翻译成限流异常并带出重试时间,调用方按类型捕获,不用解析响应体猜原因。日志只记录入参与结果摘要,密钥与完整响应体一律不进日志。

七、交付前的完整检查清单

  1. 本地起一个 Mock 网关,覆盖成功、鉴权失败、429、超时四类响应,验证错误翻译正确;
  2. 写一个最小可运行示例,从添加依赖到完成一次流式对话,全程不超 20 行调用代码;
  3. 检查配置项是否全部有默认值,密钥是否只读环境变量;
  4. 用 RestClientTest 配 MockRestServiceServer 固化请求契约,防止后续改动破坏格式;
  5. 发布后跑一遍与网关实测的联调用例,确认真实签名与响应结构一致。

版本管理上,SDK 对外承诺兼容性:接口签名变动走新版本号,小版本只做内部实现替换。release 包附一份变更记录,写明每个版本改了什么,调用方升级时能快速评估影响面。这步看似琐碎,却是 SDK 长期被信任的前提。

常见问题(FAQ)

Q1:SDK 为什么不用 RestTemplate?

RestTemplate 流式弱、语法旧;RestClient 支持拦截器与状态码处理,官方推荐。

Q2:鉴权信息应该怎么保存?

密钥走环境变量或配置中心,SDK 内部只读,不落盘、不进日志。

Q3:重试会不会造成重复扣费?

只对网络类错误重试,业务类错误不重试;请求带幂等键,网关侧去重。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
小码农的头像小码农认证作者

相关推荐

返回顶部