大厂Java面试实录:Spring Boot微服务 + Redis/Kafka + Prometheus/Jaeger + RAG/Agent(小Y水货版)
故事背景
场景:某互联网大厂电商事业群,正在做一个「AIGC导购+内容社区」平台:
- 用户在App里刷UGC短视频/图文,边看边买。
- 旁边有一个"AI导购"对话框:问"适合敏感肌的防晒有哪些?"AI会结合站内商品、达人测评与用户画像给出推荐。
- 业务目标:高并发、低延迟、可观测、可灰度、可风控。
人物:
- 面试官(M):语气严肃,步步加压,但讲道理。
- 小Y(Y):自称"全栈架构师",擅长把不会说成"懂一点",简单题能答,复杂题开始"我回去补一下"。
第一轮:从「一个接口」开始(Java/JVM + Spring Boot + DB/ORM)
Q1:电商首页Feed接口,怎么做分页与排序?
M: 你负责一个/feed接口,返回短视频流,要求支持"按时间/热度"排序,还要分页。你会怎么设计?
Y: 这个简单,用MySQL order by 然后 limit offset,按热度就 order by score desc,分页就 limit 20 offset 40。
M: 能跑,但大厂不这么写。你说说为什么?
Y: 因为......offset大了会慢?然后可以加索引?
M: 还行,有意识。继续。
Q2:Hibernate/JPA和MyBatis怎么选?
M: Feed写扩散、读扩散,既有复杂SQL也有简单CRUD。你会选JPA还是MyBatis?
Y: 我一般都用MyBatis,SQL写得清楚。JPA也能用,就是......有时候N+1问题。
M: 嗯,知道N+1不错。那你说说怎么解决?
Y: join fetch?或者把懒加载关了?
M: join fetch方向对,"关懒加载"是事故苗子。
Q3:连接池HikariCP为什么常用?C3P0呢?
M: 线上接口RT抖动,你怀疑连接池。HikariCP和C3P0差别?你怎么排查?
Y: HikariCP性能好,C3P0比较老。我会看一下最大连接数、等待时间,然后调大一点。
M: 只"调大"不够。你至少要会看指标,比如active/idle/pending。
Q4:JVM问题:接口偶发卡顿,你如何快速判断是GC还是锁?
M: Java 17,线上偶发卡顿2秒,你怎么判断是GC停顿还是线程阻塞?
Y: 我会看GC日志,如果有Full GC就知道了。或者用jstack看线程。
M: 方向对。能说出常用命令,算你过线。
第二轮:微服务化之后(Spring Cloud/Resilience4j + Kafka + Redis + 可观测)
Q1:从单体到微服务,你怎么拆?
M: 现在要拆成:用户、商品、订单、内容、推荐、AI导购。你按什么原则拆?
Y: 按业务拆,DDD那一套。用户就是用户,订单就是订单。
M: 还行。那"内容Feed"和"推荐"你怎么划边界?
Y: 推荐给内容提供排序结果,Feed服务负责组装返回。
M: 这个回答不错,有层次。
Q2:OpenFeign调用商品服务,超时雪崩怎么办?
M: Feed服务要批量拉商品信息,用OpenFeign。商品服务抖一下,Feed就崩。你怎么做?
Y: 加超时、重试,然后用Hystrix......哦Hystrix不维护了,用Resilience4j。
M: 继续,说具体点。
Y: 熔断、限流、隔离、降级。比如返回兜底商品信息。
M: 可以。你至少知道"兜底"。
Q3:Kafka用在什么地方?如何保证"至少一次/恰好一次"?
M: 点赞、收藏、下单、支付回调,这些事件怎么流转?Kafka怎么用?
Y: 点赞收藏用Kafka发消息,异步更新热度。至少一次就是可能重复消费,消费者做幂等。恰好一次......Kafka不是有Exactly Once吗?
M: 你说到点子上了,但"怎么做"呢?
Y: 嗯......用事务?我回去再补一下。
M: 好,开始水了。
Q4:Redis缓存:热点商品详情如何防穿透、击穿、雪崩?
M: 商品详情是热点,怎么用Redis?三大问题怎么处理?
Y: 穿透用布隆过滤器;击穿用互斥锁;雪崩加随机过期时间。
M: 回答很标准。那布隆过滤器误判怎么办?
Y: 误判就......查不到也就查不到?
M: 误判是"把不存在当存在",会放行去查DB;"把存在当不存在"才是灾难,但布隆不会出现。你概念得再稳一点。
Q5:可观测:Prometheus+Grafana、ELK、Jaeger怎么串起来?
M: 线上RT飙升,你怎么从"报警"定位到"具体哪段慢"?
Y: Prometheus报警,Grafana看图;日志用ELK查;链路用Jaeger看trace。
M: 你说的是组件清单。我要的是流程。
Y: 就......先看哪个服务慢,再点进去看span?
M: 嗯,勉强。
第三轮:AI导购上线(RAG/Agent + 向量库 + 安全风控 + 灰度)
Q1:AI导购为什么要RAG?你怎么做"企业文档问答"?
M: AI导购要回答"敏感肌防晒推荐"。为什么不用纯大模型直接生成?RAG怎么落地?
Y: 纯生成会幻觉。RAG就是先检索再生成,用向量库存文档embedding。
M: 还行。检索什么?文档怎么切?
Y: 检索商品说明、达人测评、FAQ。切块就按段落切......越短越好?
M: "越短越好"不一定。你至少知道要切块与embedding。
Q2:Agent与工具调用:让AI去查库存、算到手价,怎么防止乱调用?
M: 我们让AI具备"工具调用":查库存、算券后价、下单引导。怎么设计工具执行框架?怎么控制权限?
Y: 工具就是一些HTTP接口,AI要用就调用。权限的话加个token?
M: 这回答太飘。AI如果被Prompt注入,直接调用"给我下单100台iPhone"呢?
Y: 那就......在人审?或者加白名单。
M: 白名单方向对,但要更系统。
Q3:聊天会话内存:如何在多轮对话中既记住上下文又不爆token?
M: 用户聊10分钟,怎么做会话内存?
Y: 把历史都放进去?
M: token会爆。
Y: 那就做摘要,总结一下之前说了啥。
M: 对,这是关键点。
Q4:安全与风控:OAuth2/JWT、接口签名、反爬与限流怎么做?
M: AI导购接口容易被薅流量。你怎么做认证鉴权与风控?
Y: OAuth2发token,用JWT验签。限流用网关做,比如按IP限。反爬加验证码。
M: 还行。JWT吊销怎么做?
Y: 这个......JWT不是不能吊销吗?就等过期。
M: 你可以做黑名单或短token+刷新机制。回去补。
Q5:灰度与回滚:AIGC答案质量不好,怎么快速止血?
M: 新模型上线后转化率下降,你怎么灰度?怎么一键回滚?
Y: 用配置中心开关,按用户分桶灰度。不好就关掉回旧模型。
M: 可以。至少知道"分桶+开关"。
结束语
M: 今天先到这。你的基础题还行,复杂部分(Kafka EOS、Agent安全、JWT吊销)要补。回去等通知吧,有结果我们HR会联系你。
Y: 好的好的,我回去就"系统性学习",这次真的!
面试题参考答案(小白可学版,含业务场景与技术点)
下面把每一轮问题按"业务场景 → 推荐方案 → 关键点/坑"讲清楚。
第一轮答案:接口、DB与JVM
1)Feed分页排序如何做更合理?
- 业务场景 :内容流滚动加载,用户越往后翻,
offset越大。 - 问题 :
LIMIT offset,size会导致MySQL扫描大量行再丢弃,越翻越慢。 - 推荐方案 :
- 游标分页(Keyset Pagination) :
- 按时间:
where publish_time < lastTime order by publish_time desc limit 20 - 按热度:用
(score, id)作为游标:where (score < lastScore) or (score = lastScore and id < lastId)
- 按时间:
- 索引设计 :
- 时间流:
(publish_time, id) - 热度流:
(score, id);热度通常还需要定期重算/分桶。
- 时间流:
- 读模型:热点feed可用Redis/ZSet或ES做排序与检索。
- 游标分页(Keyset Pagination) :
2)JPA/Hibernate vs MyBatis怎么选?N+1怎么解决?
- 业务场景:简单CRUD + 少量复杂联表。
- 选型建议 :
- MyBatis:复杂SQL、强可控、性能可预期。
- JPA/Hibernate:领域模型清晰、开发快,但要管理好抓取策略。
- N+1问题:查一批主表后,对每条记录再查一次子表。
- 解决方式 :
- JPA:
join fetch、EntityGraph、批量抓取(batch size)。 - 业务层:一次性IN查询子表并在内存组装(避免循环查DB)。
- JPA:
3)HikariCP关键点与排查思路
- 为什么常用:HikariCP性能好、实现简洁、指标完善(常见于Spring Boot默认)。
- 排查指标(Micrometer/Actuator可暴露) :
active:正在被使用的连接数idle:空闲连接数pending:等待连接的线程数(飙升说明池不够或DB慢)
- 常见原因 :
- SQL慢导致连接占用时间长
- 连接泄漏(未关闭)
- 池太小/超时设置不合理
- 处理:先定位慢SQL与调用链,再调池参数;必要时做读写分离/分库分表。
4)判断GC停顿 vs 线程阻塞
- GC判断 :
- 开GC日志(JDK 11+常用):
-Xlog:gc*,safepoint:file=gc.log:time,level,tags - 看是否出现长时间STW(Stop-The-World)
- 开GC日志(JDK 11+常用):
- 线程阻塞判断 :
jstack <pid>:看是否大量线程BLOCKED/WAITING,是否争用同一把锁jcmd <pid> Thread.print、jfr(Java Flight Recorder)定位热点
- 经验 :
- GC导致:很多线程同时停在safepoint
- 锁/IO导致:少数关键线程卡住,其他线程排队等待
第二轮答案:微服务、消息、缓存、可观测
1)微服务怎么拆?
- 原则:以业务能力为边界(Bounded Context),降低耦合。
- 内容Feed vs 推荐 :
- 推荐服务:计算"该给用户看哪些内容/商品"(召回、排序、特征)。
- Feed服务:做接口聚合与渲染(补齐作者、商品、点赞状态),控制降级。
- 好处:推荐算法迭代频繁,和Feed高可用诉求不同,拆开更利于独立扩展。
2)Feign调用雪崩:Resilience4j怎么落地?
- 要解决的问题:下游抖动导致上游线程耗尽。
- 典型组合 :
- Timeout:严格超时(比如200~500ms)
- Bulkhead(隔离):限制并发调用数,防止线程被占满
- CircuitBreaker(熔断):错误率/慢调用超阈值,快速失败
- RateLimiter(限流):保护自己与下游
- Fallback(降级):返回缓存/默认值/部分字段
- 业务降级例子:商品服务不可用时,Feed返回"商品卡片简版"(只展示标题+价格缓存)。
3)Kafka至少一次/恰好一次怎么做?
- 业务场景:点赞事件驱动"热度"更新、推荐特征更新。
- 至少一次(At-least-once) :
- 做法:消费者先处理再提交offset,失败会重试 → 可能重复。
- 关键:幂等 (用唯一业务键去重,如
(userId, contentId, actionType))。
- 恰好一次(Exactly-once) (更复杂):
- Kafka Streams支持EOS:利用事务把"处理结果写入下游topic/状态库"和"提交offset"绑定。
- 经典难点:如果你是"消费Kafka→写MySQL",MySQL与Kafka跨系统事务很难真正EOS。
- 常用工程解:
- Outbox Pattern:业务写DB时同时写outbox表,CDC/定时任务把outbox投递到Kafka。
- 幂等+去重:多数业务接受"至少一次 + 幂等"即可。
4)Redis三大问题
- 穿透(查不存在) :
- 布隆过滤器(Bloom Filter)或缓存空值(短TTL)。
- 击穿(热点key过期瞬间) :
- 互斥锁/单飞(singleflight):只有一个线程回源构建缓存,其它等待或返回旧值。
- 雪崩(大量key同时过期) :
- TTL加随机抖动
- 多级缓存(本地Caffeine + Redis)
- 提前异步刷新
- 布隆过滤器误判 :
- 会把"不存在"误判为"可能存在"→ 放行查DB(性能损失但不影响正确性)。
- 不会把"存在"误判为"不存在"。
5)可观测联动流程
- 推荐流程 :
- Prometheus告警 :如
p99 latency、5xx、Hikari pending异常 - Grafana定位范围:哪个服务、哪个接口、从什么时候开始
- Jaeger/Zipkin查Trace:找到慢的span(如"调用商品服务800ms")
- ELK看日志:对照traceId查错误堆栈/超时原因
- 回到根因:慢SQL、下游抖动、线程池耗尽、GC等
- Prometheus告警 :如
- 实现要点 :
- 统一traceId(Spring Cloud Sleuth/OTel)
- 日志pattern带traceId
- Micrometer暴露JVM/线程池/连接池指标
第三轮答案:RAG/Agent、安全、会话、灰度
1)为什么要RAG?企业文档问答如何做?
- 业务场景:导购必须基于"真实商品信息、活动规则、达人测评"。
- 不用纯LLM原因 :LLM可能幻觉(编造不存在的成分/功效/价格)。
- RAG流程 :
- 文档加载:商品详情、成分表、测评、售后政策(文档加载器)
- 切块(chunk):按语义段落/标题,控制chunk大小(如300~800 tokens)
- 向量化:Embedding模型(OpenAI/Ollama等)
- 向量库:Milvus/Chroma/Redis Vector
- 检索:语义检索 + 关键词过滤(Hybrid Search)
- 提示填充:把检索到的证据片段拼进prompt,让模型"带引用回答"
- 评估:命中率、答案一致性、幻觉率(可用人工抽检+离线评测集)
2)Agent与工具调用:如何防乱调用(Prompt注入/越权)
- 业务场景:AI可以调用工具:查库存、查券、算到手价、创建订单草稿。
- 风险:Prompt注入让模型绕过规则,调用高危工具。
- 工程化做法 :
- 工具分级:只读工具(查库存/价格) vs 有副作用工具(下单/退款)
- 强约束参数校验 :服务端校验
userId必须来自鉴权上下文,不允许模型传 - 权限与策略:RBAC/ABAC,按用户、场景、风控分决定是否允许调用
- 工具白名单+路由:模型只能在声明的tool schema内选择
- 人机确认:高危动作必须二次确认(例如"确认购买?")
- 审计与追踪:记录每次tool call输入输出,便于追责
- 最小权限:Agent运行身份与普通用户隔离(client-server架构中,服务端代理执行)
3)会话内存怎么做(不爆token)
- 常用组合 :
- 短期窗口:保留最近N轮对话
- 摘要记忆:把较早对话压缩成摘要(summary memory)
- 向量记忆:把重要事实向量化存入向量库,按需检索回填
- 好处:既能"记得用户偏好",又控制token与成本。
4)OAuth2/JWT与吊销
- 认证建议 :
- OAuth2/OIDC登录,服务端签发JWT(或opaque token)
- Spring Security资源服务器验签
- JWT吊销常见方案 :
- 短TTL + Refresh Token:访问token很短,降低风险
- 黑名单/版本号 :在Redis存
jti黑名单或用户token版本号(登出/风控时+1) - 关键操作二次校验:支付/下单等再校验风控
- 反爬/限流:网关限流(令牌桶/漏桶)、设备指纹、验证码、行为风控。
5)灰度与回滚
- 灰度 :
- 按用户ID hash分桶(1%→5%→20%→100%)
- 按渠道/城市/新老用户定向
- 监控指标:转化率、投诉率、答案命中率、延迟与成本
- 回滚 :
- 配置中心开关(关闭新模型/关闭tool call)
- 快速切回旧模型或"纯检索模板答案"保底
你可以怎么用这套题自测
- 先把每个问题的"标准方案"说顺:一句话目标、两三条核心措施、一个坑。
- 再把"业务指标"补上:RT、QPS、转化率、幻觉率、成本。
(完)