大厂Java面试实战:Spring Boot/Cloud、Redis/Kafka、JVM调优与Spring AI RAG(内容社区UGC+AIGC客服场景)

场景:某互联网大厂「内容社区与UGC」业务线,准备上一个 AIGC 智能客服/内容审核助手。面试官(严肃、追问到细节)对候选人小Y(搞笑水货,但会一点)进行三轮面试。


角色与业务背景

  • 面试官:负责内容社区平台与AI客服系统,系统高并发、强风控、强观测。
  • 小Y:简历写了“精通Spring全家桶、JVM调优、Redis高可用、Kafka实战、Spring AI/RAG/Agent”。
  • 业务
    1. 社区UGC发帖、评论、点赞、关注
    2. 热榜与推荐需要缓存与异步
    3. 新增 AI 客服:回答“账号/订单/内容规则”等问题,支持企业知识库检索(RAG),并能调用工具查询订单/封禁状态(Agent)。

第一轮(基础到能落地):Web与数据链路

Q1:如果让你用 Spring Boot + Spring MVC 做“发帖”接口,你会怎么设计?

面试官:别只说Controller,讲讲校验、鉴权、幂等、返回结构。

小Y

  • “就 @RestController 写个 POST /posts,然后 @RequestBody 接收参数,存数据库就行。”
  • “校验的话……加个 @Valid?鉴权用 Spring Security。”

面试官(严肃但认可一点):

  • “至少知道 @Valid 和 Security。那幂等呢?”

小Y

  • “幂等……客户端别重复点?”

面试官(轻叹气):

  • “继续。”

Q2:帖子落库你用 MyBatis / JPA / Hibernate 哪个?为什么?

小Y

  • “我都行。MyBatis灵活,JPA省事。”

面试官

  • “那你在大厂常见的选择是什么?怎么做SQL可控和性能?”

小Y

  • “嗯……MyBatis吧,SQL好写。”

面试官

  • “行,至少方向没离谱。”

Q3:连接池你用 HikariCP,线上突然慢了,你先排什么?

小Y

  • “看慢SQL?”

面试官

  • “连接池也要看。说说你会关注哪些指标。”

小Y(开始含糊):

  • “看……连接数?线程数?反正就是调大一点?”

面试官

  • “调大不是答案。”

Q4:热榜接口 QPS 很高,你会怎么做缓存?用 Redis + Spring Cache/Caffeine 怎么组合?

小Y

  • “Redis做缓存,Spring Cache一加就行。Caffeine也能加。”

面试官

  • “说得像背书。缓存穿透/击穿/雪崩怎么处理?”

小Y

  • “穿透就……加布隆?击穿加锁?雪崩随机过期?”

面试官(终于表扬一句):

  • “OK,至少把关键词都说对了。下面进入第二轮。”

第二轮(分布式与可观测):异步链路、微服务、故障演练

Q1:发帖成功后要异步做“敏感词审核 + 图片鉴黄 + 推荐入库”,你会用 Kafka / RabbitMQ 哪个?为什么?

小Y

  • “Kafka吞吐高,适合日志流;RabbitMQ适合业务消息。”

面试官

  • “那你这里选哪个?以及如何保证不丢消息?”

小Y

  • “选Kafka吧,量大。保证不丢就……多副本?”

面试官(追问):

  • “生产端幂等、ACK、重试、消费端幂等你都没说。”

小Y

  • “啊对对对,也要做幂等。”

Q2:微服务调用你用 OpenFeign,怎么做超时、重试、熔断、限流?

面试官:提示:Resilience4j。

小Y

  • “在Feign里配超时,重试……就重试。熔断用Hystrix?(突然想起)啊Hystrix不维护了,用Resilience4j。”

面试官(点头):

  • “知道Hystrix退场这点可以。那隔离策略、重试风暴怎么避免?”

小Y

  • “隔离……线程池?重试风暴……少重试?”

面试官

  • “不够具体。”

Q3:线上出现“偶发500,链路很长”,你怎么做观测?

技术栈限定:Micrometer + Prometheus + Grafana + ELK + Jaeger/Zipkin。

小Y

  • “日志用ELK,指标Prometheus,链路Jaeger。然后看Grafana面板。”

面试官

  • “怎么打通 traceId?怎么做结构化日志?如何定位是DB慢还是下游慢?”

小Y(开始冒汗):

  • “traceId……放MDC?结构化就JSON日志?然后……看慢查询?”

面试官

  • “勉强算答到点上。”

Q4:你如何用 Docker + Jenkins/GitLab CI + Kubernetes 把服务发到集群?

小Y

  • “写Dockerfile,然后Jenkins构建推镜像,再kubectl apply。”

面试官

  • “灰度/回滚/探针/资源限制怎么做?”

小Y

  • “灰度……改副本数?回滚用rollout undo?探针……有readiness/liveness。”

面试官

  • “比上一题好一点,进入第三轮:AI部分。”

第三轮(AI落地与工程化):Spring AI、RAG、Agent、向量库与幻觉

Q1:我们做“智能客服”,要求基于企业知识库回答,不能瞎编。你如何用 RAG(检索增强生成) 设计?

小Y

  • “RAG就是先查资料再问大模型。把文档放向量库,查到相关的拼到prompt里。”

面试官

  • “向量化怎么做?用什么Embedding?检索怎么避免召回垃圾?”

小Y

  • “Embedding用OpenAI或者Ollama。避免垃圾就……topK小一点?”

面试官

  • “太玄学。”

Q2:我们希望客服能“查订单状态/封禁状态”,这不是纯聊天,需要调用内部接口。你怎么做 Agent(工具调用)

小Y

  • “Agent就是让模型自己调用工具。Spring AI支持工具函数。”

面试官

  • “那工具参数校验、鉴权、审计怎么做?怎么防止模型乱调?”

小Y

  • “就……加白名单?然后记录日志。”

面试官

  • “还不够。继续。”

Q3:你如何处理 AI幻觉(Hallucination)?给我工程化手段,不要口号。

小Y

  • “让它别瞎说……在prompt里写‘不要编造’。”

面试官(冷笑一声):

  • “这就是你简历里的‘精通AIGC安全与风控’?”

小Y

  • “我……也可以加引用来源。”

面试官

  • “继续,怎么强制引用?怎么做置信度?”

小Y

  • “呃……做打分?”

Q4:如果要支持多轮对话,你怎么做 聊天会话内存?如何避免越聊越慢?

小Y

  • “把历史消息存起来就行,比如Redis。”

面试官

  • “存全部?怎么做摘要?怎么做窗口?怎么做用户隔离?”

小Y

  • “摘要……让模型总结一下?窗口……只取最近几轮?”

面试官(终于给点肯定):

  • “方向对,但落地细节要更工程化。”

面试结束

面试官

  • “今天先到这。你整体基础还行,但复杂问题回答偏虚。回去把分布式一致性、消息可靠性、观测以及RAG/Agent工程化再补一补。我们会综合评估,后续等通知。”

小Y

  • “好的好的,我回去……就补(疯狂打开收藏夹)。”

题目答案详解(按轮次逐题给出可落地方案)

目标:把上面每个问题都讲清楚:业务场景 → 技术选型 → 关键细节 → 常见坑 → 建议实现


第一轮答案

A1:Spring Boot + Spring MVC 设计“发帖”接口(校验/鉴权/幂等/返回结构)

业务点:UGC发帖高并发且涉及内容安全,必须可追踪、可回放、可防重。

推荐接口POST /api/v1/posts

  • 请求:title、content、mediaIds、topicId、clientRequestId(客户端幂等键)
  • 响应:统一结构(code/message/data/traceId)

关键实现

  1. 参数校验:Jakarta Validation
    • @Valid + @NotBlank @Size;全局异常处理 @RestControllerAdvice
  2. 鉴权:Spring Security + JWT/OAuth2
    • 网关/服务端校验 JWT,拿到 userId
  3. 幂等
    • 方案一:clientRequestId + userId 做唯一键(DB唯一索引)
    • 方案二:Redis SETNX key value EX 60s(适合短时间防重复提交)
  4. 返回结构与可观测
    • 在响应中返回 traceId(来自MDC)便于排障

A2:MyBatis vs JPA/Hibernate 的选择(大厂常见做法)

结论倾向:核心交易/UGC主链路更常见 MyBatis(SQL可控、便于优化); 中后台/简单CRUD可用 Spring Data JPA 提效。

为什么MyBatis更常见

  • 复杂查询、分页、联合索引优化可控
  • 易做分库分表后SQL治理

配套建议

  • SQL审计(慢SQL日志、Explain)
  • Mapper层约束(禁止全表扫描、强制limit)

A3:HikariCP 线上慢:优先看什么指标/现象

常见现象:接口RT飙升但CPU不高,线程大量阻塞在拿连接。

应关注

  • active connections(正在使用)
  • idle connections(空闲)
  • pending threads(等待连接的线程数)
  • connectionTimeout 是否触发
  • DB侧:max_connections、慢查询、锁等待

排查路径

  1. Grafana/Prometheus 看连接池指标(Micrometer可采集)
  2. 看线程栈:大量阻塞在 DataSource.getConnection()
  3. 看是否 连接泄漏:开启 Hikari leakDetectionThreshold(谨慎,生产只短期开)
  4. 连接池不是越大越好:
    • 连接数过大 → DB上下文切换与锁竞争增加

A4:热榜缓存:Redis + Caffeine + Spring Cache 组合拳

业务点:热榜QPS高、读多写少、允许秒级延迟。

推荐架构

  • 本地缓存:Caffeine(毫秒级,抗抖动)
  • 分布式缓存:Redis(跨实例共享)
  • 回源:DB/ES

Spring Cache落地

  • @Cacheable(cacheNames="hotRank", key="#page")
  • 二级缓存可用自定义 CacheManager 或在服务层手写“Caffeine→Redis→DB”

三大问题处理

  • 穿透:参数校验 + 缓存空值(短TTL)+ Bloom Filter(可选)
  • 击穿:热点key互斥锁(Redis分布式锁)或 @Cacheable(sync=true)(单机有效)
  • 雪崩:TTL随机化 + 分批预热 + 限流降级

第二轮答案

B1:Kafka vs RabbitMQ(审核/推荐异步链路)与“消息不丢”

业务点:发帖后触发多条异步任务:文本审核、图片审核、推荐特征抽取。

选型

  • Kafka:高吞吐、可回放、天然分区扩展;适合事件流与多下游订阅
  • RabbitMQ:路由灵活、延迟队列方便;适合业务命令型消息

此场景更适合 Kafka(PostCreatedEvent)

  • 多消费组:审核组、推荐组、风控组互不影响

不丢消息关键点

  1. 生产端:
    • acks=allretriesenable.idempotence=true(幂等生产)
    • 发送失败进入补偿表(Outbox/本地消息表)
  2. Broker:
    • 合理副本数、min.insync.replicas
  3. 消费端:
    • 业务幂等:以 eventId 做去重(Redis/DB唯一键)
    • 手动提交offset:处理成功再commit
  4. 反压与重试:
    • 死信/重试主题(retry topic)

B2:OpenFeign + Resilience4j:超时/重试/熔断/限流如何配

基本原则

  • 超时,再谈重试;重试只对幂等读请求
  • 避免重试风暴:指数退避 + 限制最大并发

典型配置

  • Feign:connectTimeout/readTimeout
  • Resilience4j:
    • CircuitBreaker:失败率阈值、半开窗口
    • Retry:仅GET等幂等接口;失败异常白名单
    • Bulkhead(隔离):信号量/线程池隔离,保护主线程
    • RateLimiter:对下游或本服务做限流

重试风暴治理

  • 全链路只允许“单层重试”(例如网关不重试,客户端重试一次)
  • 大面积失败时熔断快速失败,配合降级兜底

B3:可观测:日志/指标/链路如何串起来定位500

落地组合

  • 指标:Micrometer → Prometheus → Grafana
  • 日志:Logback/Log4j2 JSON日志 → ELK
  • 链路:OpenTelemetry/Brave → Jaeger/Zipkin

关键点

  1. traceId 贯通
    • HTTP入口生成 traceId
    • 放入 MDC:MDC.put("traceId", ...)
    • 日志pattern输出traceId
  2. 结构化日志:JSON字段包含:traceId、userId、uri、cost、errorCode
  3. 定位方法
    • Grafana看 p95/p99 延迟 & 错误率 → 锁定服务
    • Jaeger按traceId看span耗时 → 判断是DB慢/下游慢
    • ELK按traceId聚合日志 → 还原请求上下文

B4:Docker + CI/CD + Kubernetes 上线(灰度/回滚/探针)

标准流水线

  1. Git push → CI(Jenkins/GitLab CI)
  2. 单测(JUnit5/Mockito)+ 静态检查
  3. 构建镜像(Docker build)→ 推镜像仓库
  4. 部署(Helm/Kustomize/kubectl apply)

K8s关键配置

  • readinessProbe:未就绪不接流量(防止冷启动抖动)
  • livenessProbe:卡死自动重启
  • resources requests/limits:避免抢占导致抖动
  • 滚动更新:maxSurge/maxUnavailable
  • 回滚:kubectl rollout undo

灰度

  • 基础:分批发布(先10%副本)
  • 进阶:服务网格/网关按用户ID或header做流量染色

第三轮答案(AI工程化)

C1:RAG 设计:向量化、检索、召回质量

目标:客服回答必须基于知识库,不允许编造。

标准RAG流程

  1. 文档加载:PDF/HTML/DB(Spring AI Document Readers)
  2. 切分Chunk:按语义/标题切分,控制chunk大小(如 300~800 tokens)
  3. 向量化Embedding:OpenAI/Ollama embedding模型
  4. 入向量库:Milvus/Chroma/Redis Vector
  5. 查询:用户问题 → 向量检索 topK →(可选)重排序rerank → 组装prompt → LLM生成

提升召回质量的手段

  • chunk切分带元数据:文档来源、章节、更新时间、权限标签
  • 过滤:按业务域/产品线过滤(metadata filter)
  • rerank:对topK做交叉编码器重排(提升相关性)
  • 设定最小相似度阈值:低于阈值直接走“无法确认+引导转人工”

C2:Agent 工具调用(查订单/封禁):参数校验、鉴权、审计、防乱调

核心:模型只能“建议调用”,真正执行必须由你控制。

落地做法

  • 工具清单(tool registry):只暴露少量安全工具
  • 参数Schema:对每个工具定义严格入参(例如订单号格式、长度)
  • 鉴权:工具执行前校验用户身份/权限(Spring Security)
  • 审计:记录 toolName、args、userId、traceId、结果摘要
  • 防乱调:
    • 只允许白名单工具
    • 频率限制(RateLimiter)
    • 对高风险工具加“二次确认”

示例工具

  • getOrderStatus(orderId)
  • getBanReason(userId)

C3:AI幻觉治理(工程手段)

不要只靠prompt,要用“检索约束 + 输出约束 + 评估与兜底”。

可落地的组合:

  1. 强制引用:答案必须附带引用片段(sources),无sources则拒答
  2. 相似度阈值:检索结果低相关 → 不生成/转人工
  3. 结构化输出:JSON schema(例如 answer + citations[] + confidence)
  4. 事实一致性校验
    • 让另一个模型做“引用一致性检查”(轻量自检)
    • 或规则校验:答案中的实体必须出现在引用中
  5. 在线评估
    • 记录问题、检索片段、最终答案、用户反馈
    • 定期用Cucumber/自动化回归集评测

C4:聊天会话内存(多轮对话)与性能治理

问题:上下文越长越贵、越慢、越容易跑偏。

常见策略

  • 窗口记忆:只保留最近N轮(例如最近6轮)
  • 摘要记忆
    • 每隔若干轮做一次summary
    • summary与最近对话一起进prompt
  • 分层存储
    • Redis:短期会话(TTL)
    • DB/ES:长期审计与复盘
  • 用户隔离与安全
    • userId维度key:chat:mem:{userId}:{sessionId}
    • 敏感字段脱敏与加密(必要时Bouncy Castle)

你可以直接照抄的学习路线(与本文问题对应)

  • Spring MVC:校验、异常、统一返回、幂等
  • DB:MyBatis SQL治理 + HikariCP指标
  • Redis:三大问题 + 二级缓存
  • Kafka:幂等生产、手动提交、去重
  • Resilience4j:熔断/隔离/限流/重试策略
  • 可观测:MDC + Micrometer + Trace
  • CI/CD:K8s探针、灰度、回滚
  • Spring AI:RAG切分/向量库/阈值 + Agent工具治理 + 幻觉约束
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐