Java 客户端、Spring AI 2.0

共 44 题
#

1. 如何设计领域级 AiService 接口,既支持 Provider 替换又不丢失工具、推理和多模态特性

A 领域接口应基于业务语义定义,用领域 DTO 与适配层隔离 Provider 差异 ✓ 正确答案
B 领域接口应直接暴露 OpenAI 的 message 结构以获得最大能力
C 替换 Provider 时无需关注工具、推理、多模态等能力差异
D 领域层应依赖具体 Provider 的 SDK 以保证性能
#

2. SseEmitter 与 WebFlux Flux<ServerSentEvent> 的线程、背压、取消和部署模型如何比较

A 两者都基于非阻塞事件循环
B SseEmitter 依赖 Servlet 容器线程模型,Flux 依赖响应式事件循环并支持背压与取消传播 ✓ 正确答案
C Flux 无法与 Spring Security 等 Servlet 生态集成
D SseEmitter 天然支持背压而 Flux 不支持
#

3. WebClient 消费模型流时,客户端断开怎样传播取消并释放连接、订阅和缓冲区

A 忽略取消继续接收 Provider 全部输出
B 通过 doOnCancel/doFinally 释放连接、缓冲并记录计费状态 ✓ 正确答案
C 手动关闭 JVM 线程池
D 取消后无需处理 Provider 副作用
#

4. SseEmitter 的超时回调与异常回调在 AI 长流场景下应如何配合使用,避免悬挂连接

A 设置短超时并让连接自然超时即可
B 合理设置超时、在超时/异常回调中完成 emitter 并取消下游任务,配合心跳保活 ✓ 正确答案
C SseEmitter 不会悬挂,无需处理
D 取消下游任务会造成连接泄漏
#

5. WebFlux 背压(request(n)、onBackpressureBuffer)在 AI 流式场景下应如何避免上游生成过快

A 缓冲必须无界以避免丢数据
B 背压只影响内存不影响连接
C 慢消费者应无限等待上游
D 用 request(n) 控制节奏,onBackpressureBuffer 设上限并配合丢弃/断开策略 ✓ 正确答案
#

6. 阻塞 SDK 与响应式链混用为何可能耗尽线程或连接,如何用压测和线程转储诊断

A 内存泄漏
B 阻塞事件循环线程导致线程和连接耗尽 ✓ 正确答案
C 数据不一致
D 无影响,响应式天然支持阻塞
#

7. 端到端容量怎样由并发、平均/尾部延迟、连接数与 Token 速率共同确定

A 需综合并发、平均/尾部延迟、连接数与 Token 速率共同确定 ✓ 正确答案
B 只需按 QPS 规划即可
C 尾部延迟对容量无影响
D Provider 配额与容量规划无关
#

8. 为什么不应在 WebFlux handler 中调用阻塞 SDK(同步 HTTP)

A 阻塞 SDK 会降低代码可读性
B 阻塞 SDK 无法编译
C 会阻塞有限的 Netty 事件循环线程,导致吞吐骤降 ✓ 正确答案
D 阻塞 SDK 会占用更多内存
#

9. 流式响应中 usage 字段在最后一个 chunk 才出现,应用层如何用预估值避免误判计费

A 每个 chunk 都包含 usage,可直接计费
B 流式过程中用预估,最终以最后一个 chunk 的 usage 校准并落库 ✓ 正确答案
C usage 永远不可用,只能按字符计费
D 取消流后无需记录计费
#

10. 如何用 Context Propagation 传入 traceId、tenantId 和安全主体,避免依赖 ThreadLocal 偶然继承

A 虚拟线程无法传递任何上下文
B 直接用 ThreadLocal 即可在响应式链路可靠传递
C 上下文只影响日志不影响业务
D 用 Reactor Context + ThreadLocalAccessor 显式传递,避免偶然继承 ✓ 正确答案
#

11. 多个用户并发共享 Prompt Cache 或 ChatMemory 时,如何通过键设计和并发控制避免跨会话污染

A 只按 prompt 内容做键,忽略用户
B 键设计中包含租户/会话维度,并配合锁或原子操作控制并发 ✓ 正确答案
C 所有用户共享一个全局 memory
D 缓存无需并发控制
#

12. 服务端取消一个 Agent 任务时,怎样级联停止 RAG、MCP 和 Provider 请求,并清理未完成的资源

A 用统一取消信号级联停止 RAG、MCP、Provider,并在 finally 清理资源 ✓ 正确答案
B 取消不需要幂等
C 取消后无需清理资源
D 只取消 Provider 请求,其余环节自然停止
#

13. 流式响应完成前客户端断开时,哪些指标仍应异步落库,如何避免请求线程被日志写入阻塞

A 记录 usage、延迟、取消等指标并异步落库,避免阻塞请求线程 ✓ 正确答案
B 断开后无需记录任何指标
C 在请求线程同步写日志
D 只记录错误不记录 usage
#

14. Spring AI 响应式调用中如何避免阻塞线程并保持错误可传播(异常映射到响应流与业务状态码)

A 用 onErrorResume/onErrorMap 把异常映射为业务错误码与响应结构,保持非阻塞 ✓ 正确答案
B 吞掉所有异常直接返回 200
C 用 block() 等待结果并捕获异常
D 异常只能返回 500
#

15. 原生 HTTP、官方 SDK、Spring AI 2.0 与 LangChain4j 1.x 应按控制力、生态和锁定风险如何选型

A 原生 HTTP 控制力最弱
B 所有方案控制力相同
C Spring AI 2.0 与 Spring 生态深度集成,但需关注 API 变动与锁定风险 ✓ 正确答案
D 官方 SDK 支持多 Provider 切换
#

16. 连接池、代理、超时、序列化、错误映射和配置刷新怎样在 Java 客户端中统一治理

A 错误映射只能返回 HTTP 500
B 每个调用点各自配置连接池
C 脚本硬编码配置
D 集中配置连接池、超时、序列化、错误映射并支持动态刷新 ✓ 正确答案
#

17. Spring AI 2.0 原生 MCP Client/Server 双角色和 Streamable HTTP 接入现有应用时要关注哪些边界

A 连接生命周期、鉴权、工具 Schema 同步、超时与降级,以及对外暴露工具的权限边界 ✓ 正确答案
B 无需处理 Streamable HTTP 的流式与取消
C 只关注能否调用外部工具
D MCP 工具无需鉴权
#

18. LangChain4j AI Services 的声明式抽象与 Spring AI Advisors 适合哪些不同团队和应用结构

A 两者完全等价
B LangChain4j 无法与 Spring 组合
C Spring AI Advisors 不适合大型应用
D LangChain4j 声明式适合快速搭建,Spring AI Advisors 适合深度 Spring 生态与精细控制 ✓ 正确答案
#

19. Spring AI 2.0 中多模型路由(OpenAI、Anthropic、Ollama 本地)应如何配置与切换,failover 与能力差异如何治理

A 通过多 Bean + 路由策略选模型,配合 failover 与能力差异治理 ✓ 正确答案
B 只能使用一个 Provider
C failover 无需关注能力差异
D 本地模型无法参与路由
#

20. 为什么 OpenAI 兼容端点仍需 Provider 契约测试,而不能假设所有字段与流事件一致

A 兼容端点完全一致,无需测试
B 不同 Provider 在字段、流事件、错误码、工具格式上存在差异,需契约测试固化 ✓ 正确答案
C 契约测试只针对 OpenAI 官方
D 契约测试无法发现兼容差异
#

21. Spring AI 2.0 升级时(1.x → 2.0)有哪些破坏性变更,应用代码应做哪些前置评估

A 直接升级无需评估
B 破坏性变更仅影响类名不影响行为
C 升级后无法回滚
D 对照迁移指南识别破坏性变更,用兼容性测试与灰度回滚保障 ✓ 正确答案
#

22. Java 客户端的 Provider 配置(API Key、Endpoint、Region)应如何外置化与轮换,避免硬编码与凭证泄漏

A 外置到 Secret Manager,支持动态轮换与最小权限、审计 ✓ 正确答案
B 直接硬编码到配置文件中
C 轮换必须重启服务
D key 可以写入日志方便排查
#

23. Spring AI 2.0 中的 ModelOptions(温度、Top-P、最大输出)应如何按业务封装而非裸用

A 每个调用点直接写温度等参数
B 按业务场景封装参数模板,集中配置并按业务类型加载 ✓ 正确答案
C 参数只能硬编码
D 参数封装无助于成本控制
#

24. Java 客户端如何统一处理 Provider 特定错误(OpenAI invalid_request_error、Anthropic overloaded_error)

A 每个 Provider 各自处理,互不统一
B overloaded_error 应无条件重试
C 所有 Provider 错误码相同
D 把 Provider 错误归一为领域错误分类,按分类决定重试/降级/告警 ✓ 正确答案
#

25. 为什么不能假设 Spring AI 升级完全向后兼容,框架版本管理应纳入变更审计

A 版本升级无需测试
B 可假设升级完全向后兼容
C 升版本应作为变更审计,评估影响并做回归验证 ✓ 正确答案
D 框架变更是可预期的
#

26. Micrometer Observation 与 OpenTelemetry Context 如何跨 Reactor、虚拟线程和回调保持关联

A 依赖 ThreadLocal 自动继承即可
B 通过 Context Propagation 与 contextWrite 在 Reactor、虚拟线程、回调中显式传递 ✓ 正确答案
C 异步边界无法保持 trace
D Observation 与 OTel 无关
#

27. 客户端取消后 Provider 仍继续输出时,Java 服务怎样丢弃晚到事件并准确记录计费状态

A 继续把晚到事件推给客户端
B 无需处理取消后的输出
C 晚到事件也要计费
D 丢弃晚到事件,关闭连接,并准确记录"已取消"的计费状态 ✓ 正确答案
#

28. Java 服务端流式响应遇到慢消费者(slow consumer)时,背压、缓冲上限与断开策略应如何设计

A 无限缓冲等待消费者
B 用背压限速、设缓冲上限,超限用丢弃或断开策略兜底 ✓ 正确答案
C 阻塞生产线程等待消费者
D 慢消费者无需处理
#

29. Spring AI 2.0 的 Flux<ChatResponse> 取消(dispose)是否会自动关闭 Provider 连接

A 取消会传播信号,但应主动用 doFinally 补充清理并验证连接确实关闭 ✓ 正确答案
B 取消与连接无关
C 必然自动关闭,无需处理
D dispose 不会释放缓冲
#

30. Provider 抛错时,Java 客户端的异常(WebClientException)应如何映射为业务异常与 HTTP 状态码

A 直接把 Provider 原始异常抛给客户端
B 异常映射无需统一
C 把底层异常映射为业务异常并分派合适的 HTTP 状态码与错误结构 ✓ 正确答案
D 所有异常统一返回 500
#

31. 如何为 Java AI 接口设计限流舱壁与 Bulkhead,区分慢 Provider、突发流量和单租户异常

A 慢 Provider 不需要隔离
B 只需一个全局限流即可
C 舱壁只影响一租户
D 用 RateLimiter 控速、Bulkhead 隔离 Provider/租户、熔断快速失败,分层治理 ✓ 正确答案
#

32. Spring AI 2.0 已 GA 且基于 Spring Boot 4.x,其 ChatClient 与 Advisor 链怎样划分职责?

A ChatClient 负责 RAG 与记忆
B Advisor 负责执行模型调用
C ChatClient 负责模型调用,Advisor 负责横切关注点(RAG、记忆、日志、安全) ✓ 正确答案
D 两者职责相同
#

33. Spring AI Advisor 链(SimpleLoggerAdvisor、MessageChatMemoryAdvisor、QuestionAnswerAdvisor、ToolCallAdvisor)的执行顺序与异常传播如何设计

A Advisor 顺序任意,不影响正确性
B 日志 Advisor 应在最内层
C 顺序决定上下文组装(记忆→RAG→工具),异常采用降级与快速失败结合并统一观测 ✓ 正确答案
D 异常应全部吞掉
#

34. Spring AI 的 ToolCallback 注解(@Tool、@ToolParam)与 Java 21 Record 在描述生成上有何局限,如何补充自定义描述

A 注解自动生成足够精确的描述
B 默认描述较简略,复杂类型需用 @ToolParam/@Tool 显式补充描述与约束 ✓ 正确答案
C Record 无法生成任何描述
D 描述不影响模型选参
#

35. Spring AI ChatClient 与 RAG Advisor 整合向量库(pgvector、Qdrant、Weaviate)时应注意哪些版本兼容与事务边界

A 无需关注版本兼容
B 检索必须放入长事务
C 向量库与 DB 版本无关
D 版本兼容与事务边界(检索轻量、写入一致、索引异步) ✓ 正确答案
#

36. JSpecify 空安全注解如何减少 Provider 响应缺字段导致的运行时问题

A 注解能完全消除空指针
B 缺字段无需处理
C 注解无法配合校验
D 注解配合静态分析提供编译期提示,运行时校验兜底缺字段 ✓ 正确答案
#

37. JEP 491(虚拟线程免 pinning)与 Spring AI 客户端调用配合时,HTTP 连接池是否需要同步升级

A 虚拟线程后连接池无需调整
B 虚拟线程提升并发但连接池仍有限,需同步校准连接池与 Provider 配额 ✓ 正确答案
C 连接池无限即可
D 虚拟线程解决连接瓶颈
#

38. 应怎样防止 Advisor 与 Spring AI ChatClient 组合后引发“重复扣费”

A 无需理会,框架自动去重
B 控制模型调用次数并用请求 ID 去重记账,监控每请求调用次数 ✓ 正确答案
C 重复调用不产生费用
D 关闭所有重试即可根治
#

39. 虚拟线程适合哪些阻塞式 AI 调用,JEP 491 后仍需关注哪些同步和连接池瓶颈

A 虚拟线程彻底解决所有并发瓶颈
B 虚拟线程不适用任何阻塞调用
C 虚拟线程无任何限制
D 适合阻塞式 AI 调用,但 pinning、连接池与 Provider 配额仍需关注 ✓ 正确答案
#

40. Scoped Values(JDK 25 正式)如何传递 traceId 和用户上下文,异步边界如何避免丢失

A 自动跨异步线程继承
B 不可变、按边界绑定,跨异步边界需显式传递避免丢失 ✓ 正确答案
C 与 ThreadLocal 等价
D 只能用于 traceId
#

41. Mono/Flux 与 Kotlin Coroutine 在 Spring AI 项目中应如何选型,二者互操作性如何

A 两者不可互操作
B Coroutine 无法用于 Spring
C Flux 更适合 Kotlin
D 取决于团队语言与背压需求,二者可互操作并混用 ✓ 正确答案
#

42. JEP 491 后虚拟线程的 pinning 问题(synchronized 阻塞平台线程)在 AI 调用链中应如何检测与规避

A pinning 无影响
B 只能在未来 JDK 解决
C synchronized 内阻塞会 pinning 平台线程,需缩小临界区或改用锁,用线程转储/JFR 检测 ✓ 正确答案
D 虚拟线程永不 pinning
#

43. 为什么在 Java 服务端应用 AI 时仍需关注 GC(ZGC、G1)

A GC 与 AI 无关
B 高对象分配与长上下文带来 GC 压力,需监控停顿与内存并选择合适收集器 ✓ 正确答案
C 只需用默认 G1
D ZGC 无停顿
#

44. Spring AI 在 Spring Boot 3.5+ 上与 Project Reactor 集成的背压处理与 SSE 流的最佳实践

A 无限缓冲并阻塞生产
B 用 block() 阻塞等待
C 无需处理取消
D 非阻塞、有界背压、心跳超时、取消清理与可观测 ✓ 正确答案