大厂Java面试实战:Spring Boot/Cloud、Redis/Kafka、JVM调优与Spring AI RAG(内容社区UGC+AIGC客服场景)
以“内容社区+UGC+AIGC智能客服”为业务背景,模拟大厂Java面试:严肃面试官循序渐进提问Spring Boot/Cloud、JVM、Redis、Kafka、数据库、观测、CI/CD与Spring AI/RAG/Agent等,小Y简单题会答复杂题含糊。文末给出每题详细答案与落地方案,便于小白系统学习。
大厂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”。
- 业务:
- 社区UGC发帖、评论、点赞、关注
- 热榜与推荐需要缓存与异步
- 新增 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)
关键实现:
- 参数校验:Jakarta Validation
@Valid+@NotBlank @Size;全局异常处理@RestControllerAdvice
- 鉴权:Spring Security + JWT/OAuth2
- 网关/服务端校验 JWT,拿到 userId
- 幂等:
- 方案一:
clientRequestId + userId做唯一键(DB唯一索引) - 方案二:Redis
SETNX key value EX 60s(适合短时间防重复提交)
- 方案一:
- 返回结构与可观测:
- 在响应中返回
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、慢查询、锁等待
排查路径:
- Grafana/Prometheus 看连接池指标(Micrometer可采集)
- 看线程栈:大量阻塞在
DataSource.getConnection() - 看是否 连接泄漏:开启 Hikari leakDetectionThreshold(谨慎,生产只短期开)
- 连接池不是越大越好:
- 连接数过大 → 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):
- 多消费组:审核组、推荐组、风控组互不影响
不丢消息关键点:
- 生产端:
acks=all、retries、enable.idempotence=true(幂等生产)- 发送失败进入补偿表(Outbox/本地消息表)
- Broker:
- 合理副本数、min.insync.replicas
- 消费端:
- 业务幂等:以
eventId做去重(Redis/DB唯一键) - 手动提交offset:处理成功再commit
- 业务幂等:以
- 反压与重试:
- 死信/重试主题(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
关键点:
- traceId 贯通:
- HTTP入口生成 traceId
- 放入 MDC:
MDC.put("traceId", ...) - 日志pattern输出traceId
- 结构化日志:JSON字段包含:traceId、userId、uri、cost、errorCode
- 定位方法:
- Grafana看 p95/p99 延迟 & 错误率 → 锁定服务
- Jaeger按traceId看span耗时 → 判断是DB慢/下游慢
- ELK按traceId聚合日志 → 还原请求上下文
B4:Docker + CI/CD + Kubernetes 上线(灰度/回滚/探针)
标准流水线:
- Git push → CI(Jenkins/GitLab CI)
- 单测(JUnit5/Mockito)+ 静态检查
- 构建镜像(Docker build)→ 推镜像仓库
- 部署(Helm/Kustomize/kubectl apply)
K8s关键配置:
- readinessProbe:未就绪不接流量(防止冷启动抖动)
- livenessProbe:卡死自动重启
- resources requests/limits:避免抢占导致抖动
- 滚动更新:
maxSurge/maxUnavailable - 回滚:
kubectl rollout undo
灰度:
- 基础:分批发布(先10%副本)
- 进阶:服务网格/网关按用户ID或header做流量染色
第三轮答案(AI工程化)
C1:RAG 设计:向量化、检索、召回质量
目标:客服回答必须基于知识库,不允许编造。
标准RAG流程:
- 文档加载:PDF/HTML/DB(Spring AI Document Readers)
- 切分Chunk:按语义/标题切分,控制chunk大小(如 300~800 tokens)
- 向量化Embedding:OpenAI/Ollama embedding模型
- 入向量库:Milvus/Chroma/Redis Vector
- 查询:用户问题 → 向量检索 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,要用“检索约束 + 输出约束 + 评估与兜底”。
可落地的组合:
- 强制引用:答案必须附带引用片段(sources),无sources则拒答
- 相似度阈值:检索结果低相关 → 不生成/转人工
- 结构化输出:JSON schema(例如 answer + citations[] + confidence)
- 事实一致性校验:
- 让另一个模型做“引用一致性检查”(轻量自检)
- 或规则校验:答案中的实体必须出现在引用中
- 在线评估:
- 记录问题、检索片段、最终答案、用户反馈
- 定期用Cucumber/自动化回归集评测
C4:聊天会话内存(多轮对话)与性能治理
问题:上下文越长越贵、越慢、越容易跑偏。
常见策略:
- 窗口记忆:只保留最近N轮(例如最近6轮)
- 摘要记忆:
- 每隔若干轮做一次summary
- summary与最近对话一起进prompt
- 分层存储:
- Redis:短期会话(TTL)
- DB/ES:长期审计与复盘
- 用户隔离与安全:
- userId维度key:
chat:mem:{userId}:{sessionId} - 敏感字段脱敏与加密(必要时Bouncy Castle)
- userId维度key:
你可以直接照抄的学习路线(与本文问题对应)
- Spring MVC:校验、异常、统一返回、幂等
- DB:MyBatis SQL治理 + HikariCP指标
- Redis:三大问题 + 二级缓存
- Kafka:幂等生产、手动提交、去重
- Resilience4j:熔断/隔离/限流/重试策略
- 可观测:MDC + Micrometer + Trace
- CI/CD:K8s探针、灰度、回滚
- Spring AI:RAG切分/向量库/阈值 + Agent工具治理 + 幻觉约束
更多推荐



所有评论(0)