大厂Java面试实战:Spring Boot微服务到MCP协议与RAG架构,谢飞机的AI时代面试之旅
大厂Java面试实战:Spring Boot微服务到MCP协议与RAG架构,谢飞机的AI时代面试之旅
📌 本文以互联网大厂Java后端面试为背景,通过面试官与水货程序员"谢飞机"的3轮对话,覆盖电商场景、微服务云原生、AI与大数据三大方向,涉及Spring Boot、Redis、Kafka、Spring Cloud、Resilience4j、gRPC、Kubernetes、Spring AI、MCP协议、RAG、向量数据库等核心技术栈。文末附详细答案解析,小白也能看懂。
🎬 人物介绍
| 角色 | 特征 | |------|------| | 面试官 | 互联网大厂技术专家,严肃专业,善于引导,由浅入深 | | 谢飞机 | 水货Java程序员,简历写得很花哨,简单问题能答,复杂问题含糊其辞 |
第一轮:电商场景 —— 从Spring Boot到消息队列
🎯 业务场景:某电商平台日活千万,核心链路包括商品浏览、下单、支付、库存扣减。面试官从项目构建切入,逐步深入到缓存与异步消息。
Q1:你在电商项目中,Spring Boot项目的构建和依赖管理是怎么做的?
面试官:谢飞机你好,先聊聊你做的电商项目。你们项目是用Maven还是Gradle构建的?Spring Boot版本是多少?
谢飞机:我们用的是Maven,Spring Boot 2.7.x……不对,后来升级到3.x了,用Java 17。就是那种spring-boot-starter-parent继承的,然后在pom.xml里加各种starter依赖,挺方便的。
面试官:嗯,不错。Maven的spring-boot-starter-parent确实简化了依赖管理。那你们Java 17升级过程中,有没有遇到什么兼容性问题?
谢飞机:呃……兼容性嘛……就是有些老库不支持……然后我们就……换了。
面试官:(微笑)好的,能升级到Java 17说明团队还是有技术追求的。我们继续往下聊。
Q2:数据访问层你们用的什么?MyBatis还是JPA?
面试官:你们的商品数据和订单数据,持久层是怎么设计的?用的MyBatis还是Hibernate/JPA?
谢飞机:我们商品用的MyBatis,因为SQL好优化嘛,特别是列表查询、分页那些。订单的话用的JPA,因为订单实体关系比较复杂,一对多、多对多,JPA写起来方便。
面试官:回答得不错,技术选型有区分度。那你们连接池用的什么?HikariCP还是Druid?
谢飞机:HikariCP,Spring Boot默认带的,性能好。
面试官:很好。HikariCP确实是性能最优的连接池之一。那你们有没有做过数据库版本管理?比如Flyway或Liquibase?
谢飞机:呃……Flyway……就是写SQL脚本放到指定目录……然后它自己跑……具体的细节我有点记不清了。
面试官:没关系,思路是对的。Flyway确实是把SQL脚本按版本号顺序执行。
Q3:电商场景下Redis缓存怎么设计?缓存一致性问题怎么解决?
面试官:你们电商平台商品详情页QPS很高,Redis缓存是怎么设计的?如果数据库更新了,缓存怎么保证一致性?
谢飞机:Redis嘛,我们用的就是缓存那五大类型,String存商品信息,Hash存购物车,ZSet做排行榜。一致性的话……就是先更新数据库,再删除缓存……大概就是Cache Aside模式吧。
面试官:嗯,Cache Aside是最常用的模式。那你有没有遇到过缓存穿透、缓存击穿、缓存雪崩的问题?怎么解决的?
谢飞机:穿透就是查不存在的数据嘛,可以用布隆过滤器……击穿就是热点key过期了……可以用互斥锁……雪崩就是大量key同时过期……加随机过期时间……
面试官:思路是对的,但听起来不够自信啊。布隆过滤器、互斥锁、随机过期时间,这些方案你实际落地过吗?
谢飞机:呃……布隆过滤器是同事做的,我主要负责写CRUD……
面试官:(点头)好的,了解了。
Q4:订单系统的高并发处理,你们怎么用Kafka做异步解耦的?
面试官:双十一大促的时候,订单峰值TPS可能上万。你们下单流程中,哪些环节用了Kafka做异步处理?
谢飞机:我们下单的时候,先创建订单写库,然后发一条消息到Kafka,下游的库存服务、积分服务、通知服务各自消费。这样下单接口就不用同步等它们了,响应快。
面试官:思路不错。那Kafka怎么保证消息不丢?比如订单消息发出去,库存没扣,怎么办?
谢飞机:呃……producer那边可以设acks=all……然后consumer那边手动提交offset……大概就是这样吧。
面试官:acks=all和手动提交offset是对的方向。那如果是消息重复消费呢?比如库存扣了两次?
谢飞机:呃……幂等……就是做幂等……怎么做的……我……用Redis做去重……大概……
面试官:好的,幂等确实可以通过Redis SETNX或数据库唯一约束来实现。这部分你还需要再深入了解一下。
第二轮:微服务与云原生 —— 从服务治理到容器化部署
🎯 业务场景:随着电商业务增长,单体架构拆分为微服务。面试官从服务注册发现切入,逐步深入到服务间通信、容错降级、容器编排和监控体系。
Q5:你们的微服务架构是怎么做服务注册和发现的?
面试官:谢飞机,你们从单体拆成微服务后,服务注册发现用的什么?Eureka还是Consul?
谢飞机:用的Spring Cloud Alibaba那套……Nacos做注册中心。之前用过Eureka,但是Eureka 2.0不维护了,就换Nacos了。
面试官:不错,技术选型有考量。Nacos确实同时支持注册中心和配置中心,比较方便。那你们服务间调用用的什么方式?
谢飞机:OpenFeign,声明式调用,写个接口加个@FeignClient注解就行,很方便。
面试官:很好,OpenFeign确实简洁优雅。回答得很准确。
Q6:微服务调用链路中,如果某个下游服务挂了,你们怎么做熔断降级?
面试官:大促期间订单服务调用库存服务,如果库存服务响应变慢或挂了,你们怎么保护订单服务不被拖垮?
谢飞机:用熔断器……之前用过Hystrix,后来换成Resilience4j了,因为Hystrix不维护了。就是配置一个熔断规则,当失败率达到阈值就熔断,走降级逻辑。
面试官:嗯,Resilience4j确实是Hystrix的替代方案。那你能说说Resilience4j的核心组件有哪些吗?熔断器的状态机是怎么转换的?
谢飞机:核心组件……有CircuitBreaker……还有Bulkhead、RateLimiter、Retry……状态机嘛……就是CLOSED、OPEN、HALF_OPEN……CLOSED状态下失败率高了就变OPEN……OPEN等一段时间变HALF_OPEN……HALF_OPEN试试看成功就回CLOSED,失败就回OPEN……
面试官:非常好!状态机转换描述得很准确。Resilience4j的核心组件你也说对了。看来你对熔断器是有一定了解的。
Q7:你们微服务间有没有用gRPC?它和REST有什么区别和适用场景?
面试官:除了OpenFeign做REST调用,你们内部服务间有没有用gRPC?
谢飞机:用过。gRPC就是基于HTTP/2的,用Protobuf做序列化,性能比REST好。适合内部服务间高频调用。REST用的是JSON,可读性好,适合对外暴露API。
面试官:总结得不错。那Protobuf相比JSON,序列化性能优势主要在哪?
谢飞机:呃……Protobuf是二进制的,体积小……然后有Schema定义……序列化速度快……JSON要解析字符串嘛,比较慢……
面试官:对,Protobuf的二进制编码和Schema机制确实带来了性能优势。那你们gRPC的Protobuf文件是怎么管理的?多个服务之间的proto文件版本兼容怎么处理?
谢飞机:呃……proto文件就是放在一个公共仓库里……版本兼容……就是加字段用optional……删字段要小心……具体的我……
面试官:没关系,proto文件公共仓库管理是常见做法,版本兼容方面用optional和reserved字段是正确方向。可以再深入了解一下。
Q8:你们的服务是怎么部署到Kubernetes上的?CI/CD流程是怎样的?
面试官:聊到部署了,你们微服务是怎么上Kubernetes的?从代码提交到部署上线,整个CI/CD流程是怎样的?
谢飞机:我们用的GitLab CI……开发提交代码到GitLab,触发Pipeline……先编译打包跑测试,然后构建Docker镜像推到镜像仓库……再用kubectl或者Helm部署到K8s集群。
面试官:流程很标准。那K8s里你们怎么配置服务的滚动更新和回滚?
谢飞机:滚动更新就是Deployment的默认策略嘛……maxSurge和maxUnavailable配置一下……回滚就是kubectl rollout undo……
面试官:很好,回答正确。那你们有没有做蓝绿部署或金丝雀发布?
谢飞机:呃……金丝雀就是先用一小部分流量试试……可以用Istio做流量切分……但是……我们实际没怎么用过……主要是滚动更新就够了……
面试官:了解。金丝雀发布在大厂确实更常见,特别是需要灰度验证的场景。
Q9:K8s环境下,你们微服务的监控和链路追踪是怎么做的?
面试官:最后聊聊运维监控。你们K8s上的微服务,指标监控和链路追踪分别用什么?
谢飞机:监控用的Prometheus + Grafana……Spring Boot Actuator集成Micrometer,把指标暴露给Prometheus抓取……Grafana做可视化看板。链路追踪用的Jaeger……Spring Cloud Sleuth生成traceId和spanId,通过HTTP header传递。
面试官:技术栈很全面。那Micrometer和Prometheus之间是怎么对接的?你能说说具体的配置吗?
谢飞机:就是加micrometer-registry-prometheus依赖……然后在application.yml里暴露prometheus端点……Prometheus那边配scrape config抓取/actuator/prometheus……
面试官:非常好,配置描述准确。看来你对监控体系是有实际经验的。
第三轮:AI与大数据 —— 从Spring AI到MCP协议与RAG架构
🎯 业务场景:电商业务升级,需要引入AI能力做智能客服、商品推荐和企业内部知识库问答。面试官从Spring AI接入大模型切入,深入到MCP协议、RAG架构和向量数据库选型。
Q10:你们有没有在Java项目中集成大语言模型?Spring AI怎么用的?
面试官:谢飞机,现在AI很火,你们电商项目有没有接入大模型?比如智能客服或者商品推荐?
谢飞机:有的,我们用Spring AI接了OpenAI的GPT模型……就是加spring-ai-openai-spring-boot-starter依赖,配置API Key,然后用ChatClient来对话。
面试官:不错,ChatClient是Spring AI的核心组件。那你们有没有用Embedding模型做向量化?
谢飞机:Embedding……就是把文本转成向量……用EmbeddingModel接口……可以接OpenAI的或者本地Ollama的……然后存到向量数据库里。
面试官:很好,思路是对的。Spring AI的EmbeddingModel确实提供了统一的向量化抽象。
Q11:MCP模型上下文协议你了解吗?它的架构和核心组件是什么?
面试官:你们接了大模型之后,大模型怎么调用你们的外部工具和数据的?有没有了解过MCP协议?
谢飞机:MCP……就是Model Context Protocol……Anthropic提出来的……是一个开放协议,标准化大模型和外部工具的连接……
面试官:嗯,概念是对的。那MCP的架构是怎样的?核心组件有哪些?
谢飞机:架构是……客户端-服务器模式……MCP Client在大模型应用这边……MCP Server提供工具和资源……核心组件有……Tools……Resources……还有Prompts……
面试官:方向正确。那MCP和Spring AI的Function Calling有什么区别?为什么要用MCP?
谢飞机:呃……Function Calling是模型直接调函数……MCP是协议层的标准化……就是说……不同的模型和工具之间可以通用……不用每个模型单独写适配……然后……具体的集成细节我……
面试官:(点头)好的,你抓住了核心区别——MCP是协议层的标准化,而Function Calling是模型层面的能力。MCP的价值在于解耦和标准化。
Q12:RAG检索增强生成你们是怎么实现的?整个流程是怎样的?
面试官:你们有没有做企业文档问答?就是RAG那一套。整个流程能说说吗?
谢飞机:RAG嘛……就是先加载文档……然后分块……再用Embedding模型把每个块转成向量……存到向量数据库里……用户提问的时候,把问题也转成向量,去向量数据库里检索相似的文档块……然后拼到Prompt里……发给大模型生成回答。
面试官:流程描述得不错。那你们文档分块用的是什么策略?chunk size怎么确定的?
谢飞机:分块……就是按字数切……比如每500个token一个块……然后有重叠……重叠50个token左右……具体为什么这么设……我……是参考别人的配置……
面试官:好的,固定大小分块+重叠是最基础的策略。实际上还有按语义分块、按段落分块等策略。chunk size和overlap需要根据文档类型和检索效果来调优。
Q13:向量数据库你们选的什么?Milvus和Chroma有什么区别?
面试官:你们RAG的向量存储用的什么数据库?
谢飞机:我们用的Milvus……因为是分布式的,支持大规模向量检索……Spring AI有MilvusVectorStore的实现。之前试过Chroma,比较轻量,适合开发测试。
面试官:选型思路不错。那Milvus的索引类型你们用的什么?IVF_FLAT还是HNSW?
谢飞机:索引……我们用的HNSW……因为查询速度快……虽然内存占用大一点……IVF_FLAT的话……适合大规模数据……精度和速度的权衡嘛……
面试官:嗯,HNSW在查询性能上确实有优势。你对向量索引有一定了解。
Q14:Agentic RAG是什么?它和传统RAG有什么区别?AI幻觉怎么治理?
面试官:最后一个问题。你有没有了解过Agentic RAG?它和传统RAG有什么区别?另外AI幻觉问题你们是怎么处理的?
谢飞机:Agentic RAG……就是在RAG基础上加了Agent……Agent可以自主决策……比如判断要不要检索、检索几次、调用什么工具……传统RAG就是一次检索就生成……Agentic的更智能……
面试官:概念理解是对的。那AI幻觉呢?
谢飞机:AI幻觉就是模型编造不存在的信息……RAG本身就能减少幻觉,因为给了事实上下文……然后还可以……设温度参数低一点……让模型不要乱发挥……另外……可以在Prompt里加约束……让它"如果不确定就说不知道"……但是……完全消除幻觉……目前……我……不太清楚还有什么更好的方案……
面试官:好的。RAG确实能显著降低幻觉,但无法完全消除。除了你说的温度控制和Prompt约束,还可以通过多路检索交叉验证、引用溯源、置信度过滤等手段进一步治理。这些都是比较前沿的方向,你可以持续关注。
面试官:总结
面试官:好的,谢飞机,今天的面试就到这里。你对Spring Boot、MyBatis、Redis这些基础技术有一定掌握,微服务方向也了解不少。但在Kafka消息可靠性、gRPC proto管理、MCP协议集成、Agentic RAG这些深度方向上,还需要加强。你先回去等通知吧,我们会在三个工作日内给你回复。
谢飞机:好的好的,谢谢面试官!我回去一定好好学MCP和RAG!
📚 详细答案解析
以下是对全部14道面试题的详细解析,包含业务场景、技术原理、最佳实践和代码示例,适合初学者学习。
第一轮答案解析:电商场景
Q1 解析:Spring Boot项目构建与依赖管理
业务场景:电商平台需要快速迭代,Spring Boot的自动配置和starter依赖机制大幅提升开发效率。
技术原理:
- Maven构建:通过继承
spring-boot-starter-parent获得统一的依赖版本管理:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
-
Java 17升级注意事项:
- Spring Boot 3.x 最低要求Java 17
javax.*包替换为jakarta.*(Jakarta EE迁移)- 需要检查第三方依赖是否兼容Java 17
- Records、密封类、模式匹配等新特性可用
-
Gradle替代方案:
plugins {
id 'org.springframework.boot' version '3.2.0'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
最佳实践:
- 使用BOM(Bill of Materials)管理依赖版本,避免版本冲突
- 生产环境排除
spring-boot-devtools - 使用
spring-boot-maven-plugin打包可执行JAR
Q2 解析:数据访问层选型与连接池
业务场景:电商平台中,商品数据查询复杂、需要SQL优化,适合MyBatis;订单实体关系复杂,适合JPA。
技术原理:
- MyBatis vs JPA选型:
| 维度 | MyBatis | JPA/Hibernate | |------|---------|---------------| | SQL控制 | 完全控制,手写SQL | 自动生成,JPQL/HQL | | 学习成本 | 低,会SQL即可 | 高,需理解实体关系映射 | | 复杂查询 | 优秀,支持动态SQL | 较弱,复杂查询需写原生SQL | | 开发效率 | 中等,需写XML/注解 | 高,自动生成CRUD | | 适用场景 | 商品列表、报表查询 | 订单、用户等实体关系复杂场景 |
- HikariCP连接池核心配置:
spring:
datasource:
hikari:
maximum-pool-size: 20 # 最大连接数
minimum-idle: 5 # 最小空闲连接
connection-timeout: 30000 # 连接超时(ms)
idle-timeout: 600000 # 空闲超时(ms)
max-lifetime: 1800000 # 连接最大生命周期(ms)
- Flyway数据库版本管理:
src/main/resources/db/migration/
├── V1__Create_user_table.sql
├── V2__Add_product_table.sql
├── V3__Add_order_table.sql
Flyway按照版本号顺序自动执行SQL脚本,确保数据库Schema与代码版本一致。
Q3 解析:Redis缓存设计与一致性方案
业务场景:电商商品详情页QPS可达数万,直接查数据库无法承受,需要Redis缓存。
技术原理:
- Redis五大数据类型在电商中的应用:
| 数据类型 | 应用场景 | 示例 | |---------|---------|------| | String | 商品详情缓存 | SET product:1001 "{json}" | | Hash | 购物车 | HSET cart:userId productId quantity | | List | 最新订单列表 | LPUSH orders:latest orderId | | ZSet | 商品销量排行榜 | ZADD sales_rank productId salesCount | | Set | 用户标签 | SADD user:tags:1001 "vip" "new" |
- 缓存一致性 —— Cache Aside模式:
读操作:先查缓存 → 命中则返回 → 未命中则查DB → 写入缓存 → 返回
写操作:更新数据库 → 删除缓存
- 三大缓存问题及解决方案:
| 问题 | 描述 | 解决方案 | |------|------|---------| | 缓存穿透 | 查询不存在的数据,缓存和DB都没有 | 布隆过滤器 + 缓存空值 | | 缓存击穿 | 热点key过期,大量请求穿透到DB | 互斥锁 + 热点key永不过期 | | 缓存雪崩 | 大量key同时过期 | 随机过期时间 + 多级缓存 |
- 布隆过滤器代码示例:
// 使用Redisson实现布隆过滤器
RBloomFilter<Long> bloomFilter = redisson.getBloomFilter("product:exist");
bloomFilter.tryInit(1000000L, 0.01); // 预计100万数据,误判率1%
// 查询时先过布隆过滤器
if (!bloomFilter.contains(productId)) {
return null; // 商品一定不存在
}
Q4 解析:Kafka异步消息处理与可靠性保证
业务场景:电商下单流程中,创建订单后需要扣库存、加积分、发通知。同步处理导致接口耗时过长,用Kafka异步解耦。
技术原理:
- Kafka架构核心概念:
Producer → Topic (Partition) → Consumer Group
├── Consumer 1 (库存服务)
├── Consumer 2 (积分服务)
└── Consumer 3 (通知服务)
- 消息不丢失的三个层面:
| 层面 | 配置 | 说明 | |------|------|------| | Producer端 | acks=all + retries=3 | 等待所有副本确认,失败自动重试 | | Broker端 | min.insync.replicas=2 | 至少2个副本同步成功 | | Consumer端 | enable.auto.commit=false | 手动提交offset,处理完再提交 |
- 消息幂等性保证:
// 方案1:Redis SETNX去重
String key = "order:consume:" + messageId;
Boolean isNew = redisTemplate.opsForValue().setIfAbsent(key, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isNew)) {
return; // 已消费过,直接跳过
}
// 执行业务逻辑
deductInventory(orderId);
// 方案2:数据库唯一约束
// CREATE UNIQUE INDEX uk_message_id ON consume_record(message_id);
- Spring Boot集成Kafka配置:
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
acks: all
retries: 3
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer:
group-id: order-service
enable-auto-commit: false
auto-offset-reset: earliest
第二轮答案解析:微服务与云原生
Q5 解析:服务注册发现
业务场景:微服务拆分后,服务实例动态扩缩容,需要服务注册中心自动发现实例地址。
技术原理:
- Nacos vs Eureka对比:
| 维度 | Nacos | Eureka | |------|-------|--------| | 一致性协议 | Raft (CP) + Distro (AP) | AP (最终一致性) | | 配置中心 | 内置支持 | 不支持 | | 健康检查 | TCP/HTTP/自定义 | 心跳 | | 服务推送 | 主动推送变更 | 客户端轮询 | | 维护状态 | 活跃维护 | 2.x停止维护 |
- OpenFeign声明式调用:
@FeignClient(name = "inventory-service", fallback = InventoryFallback.class)
public interface InventoryClient {
@PostMapping("/api/inventory/deduct")
Result deductInventory(@RequestBody OrderRequest request);
}
// 降级处理
@Component
public class InventoryFallback implements InventoryClient {
@Override
public Result deductInventory(OrderRequest request) {
return Result.fail("库存服务不可用,请稍后重试");
}
}
Q6 解析:Resilience4j熔断降级
业务场景:大促期间库存服务负载过高,响应变慢,需要熔断保护订单服务不被级联拖垮。
技术原理:
- Resilience4j核心组件:
| 组件 | 功能 | 应用场景 | |------|------|---------| | CircuitBreaker | 熔断器 | 防止级联故障 | | Bulkhead | 舱壁隔离 | 限制并发调用数 | | RateLimiter | 限流 | 控制请求速率 | | Retry | 重试 | 临时故障自动恢复 | | TimeLimiter | 超时控制 | 防止长时间等待 |
- 熔断器状态机:
CLOSED ──(失败率≥阈值)──> OPEN ──(等待时间结束)──> HALF_OPEN
↑ │
└──────────(探测成功)────────────────────────────────┘
│
(探测失败)
↓
OPEN
- Spring Boot集成配置:
resilience4j:
circuitbreaker:
instances:
inventoryService:
register-health-indicator: true
sliding-window-size: 10 # 滑动窗口大小
minimum-number-of-calls: 5 # 最小调用次数
failure-rate-threshold: 50 # 失败率阈值(%)
wait-duration-in-open-state: 10s # OPEN状态等待时间
permitted-number-of-calls-in-half-open-state: 3 # HALF_OPEN探测次数
- 代码使用:
@CircuitBreaker(name = "inventoryService", fallbackMethod = "fallback")
public Result callInventory(OrderRequest request) {
return inventoryClient.deductInventory(request);
}
public Result fallback(OrderRequest request, Exception e) {
log.warn("库存服务熔断降级,订单: {}", request.getOrderId());
return Result.fail("系统繁忙,请稍后重试");
}
Q7 解析:gRPC与REST对比
业务场景:微服务间高频内部调用,对延迟敏感,gRPC比REST更适合。
技术原理:
- gRPC vs REST对比:
| 维度 | gRPC | REST | |------|------|------| | 协议 | HTTP/2 | HTTP/1.1 | | 序列化 | Protobuf(二进制) | JSON(文本) | | 性能 | 高(序列化快、体积小) | 中 | | 流式支持 | 双向流 | 不支持(需WebSocket) | | 可读性 | 低(二进制) | 高(JSON可读) | | 浏览器支持 | 需gRPC-Web | 原生支持 | | 适用场景 | 内部服务高频调用 | 对外API、低频调用 |
- Protobuf定义示例:
syntax = "proto3";
package com.ecommerce.inventory;
service InventoryService {
rpc DeductInventory (OrderRequest) returns (InventoryResponse);
rpc QueryInventory (ProductQuery) returns (InventoryInfo);
}
message OrderRequest {
string order_id = 1;
repeated OrderItem items = 2;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
}
message InventoryResponse {
bool success = 1;
string message = 2;
}
- Protobuf版本兼容性原则:
- 新增字段:使用新字段编号,不影响旧版本解析
- 删除字段:使用
reserved关键字保留编号,避免复用 - 字段类型变更:不兼容,需要新字段编号
Q8 解析:Kubernetes部署与CI/CD
业务场景:微服务需要容器化部署,实现弹性伸缩和滚动更新。
技术原理:
- CI/CD完整流程:
开发提交代码 → GitLab Pipeline触发
├── 阶段1: 编译打包 (mvn clean package)
├── 阶段2: 单元测试 (JUnit 5 + Mockito)
├── 阶段3: 构建Docker镜像 (docker build)
├── 阶段4: 推送镜像仓库 (docker push)
└── 阶段5: 部署K8s (helm upgrade)
- Dockerfile示例:
FROM eclipse-temurin:17-jre-alpine
COPY target/app.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar", "--spring.profiles.active=prod"]
- K8s Deployment配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 滚动更新时最多多出1个Pod
maxUnavailable: 0 # 滚动更新时不允许减少Pod
template:
spec:
containers:
- name: order-service
image: registry.cn-hangzhou.aliyuncs.com/ecommerce/order-service:v1.2.0
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
- 金丝雀发布(通过Istio流量切分):
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
spec:
http:
- route:
- destination:
host: order-service
subset: stable
weight: 90 # 90%流量到稳定版本
- destination:
host: order-service
subset: canary
weight: 10 # 10%流量到金丝雀版本
Q9 解析:监控与链路追踪
业务场景:微服务调用链路复杂,一个请求可能经过5-10个服务,需要全链路监控和追踪。
技术原理:
- 监控体系架构:
Spring Boot Actuator
└── Micrometer (指标抽象层)
└── Prometheus (指标存储)
└── Grafana (可视化看板)
Spring Cloud Sleuth / Micrometer Tracing
└── Jaeger / Zipkin (分布式链路追踪)
- Micrometer集成配置:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-jaeger</artifactId>
</dependency>
- application.yml配置:
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
metrics:
tags:
application: order-service
tracing:
sampling:
probability: 1.0 # 采样率,生产环境建议0.1
- 自定义业务指标:
@Service
public class OrderService {
private final Counter orderCounter;
private final Timer orderTimer;
public OrderService(MeterRegistry meterRegistry) {
this.orderCounter = Counter.builder("order.created.total")
.description("Total orders created")
.tag("type", "ecommerce")
.register(meterRegistry);
this.orderTimer = Timer.builder("order.creation.duration")
.description("Order creation time")
.register(meterRegistry);
}
public Order createOrder(OrderRequest request) {
return orderTimer.record(() -> {
Order order = doCreateOrder(request);
orderCounter.increment();
return order;
});
}
}
第三轮答案解析:AI与大数据
Q10 解析:Spring AI集成大语言模型
业务场景:电商平台需要AI智能客服,自动回答用户关于商品、订单、退换货的问题。
技术原理:
- Spring AI核心架构:
Spring AI
├── ChatClient → 对话生成(接OpenAI/Ollama/Azure等)
├── EmbeddingModel → 文本向量化
├── VectorStore → 向量存储抽象(Milvus/Chroma/Redis等)
├── ChatMemory → 会话记忆管理
└── Advisors → 顾问链(RAG、日志、安全等)
- ChatClient使用示例:
@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是一个电商客服助手,请友好地回答用户问题。")
.build();
}
@PostMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
- EmbeddingModel使用:
@Service
public class EmbeddingService {
private final EmbeddingModel embeddingModel;
public List<float[]> embedDocuments(List<String> documents) {
EmbeddingResponse response = embeddingModel.embedForResponse(documents);
return response.getResults().stream()
.map(Embedding::getOutput)
.toList();
}
}
- application.yml配置:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
temperature: 0.7
embedding:
options:
model: text-embedding-ada-002
Q11 解析:MCP模型上下文协议
业务场景:大模型需要调用电商系统的多个外部工具(查订单、查库存、退款等),MCP协议标准化这些工具的接入方式。
技术原理:
- MCP架构:
┌─────────────────┐ MCP协议 ┌─────────────────┐
│ MCP Client │ ←──────────────→ │ MCP Server │
│ (Spring AI App) │ │ (工具提供方) │
│ │ │ │
│ - 发起工具调用 │ │ - 暴露Tools │
│ - 管理会话 │ │ - 暴露Resources │
│ - 处理响应 │ │ - 暴露Prompts │
└─────────────────┘ └─────────────────┘
- MCP三大核心组件:
| 组件 | 功能 | 示例 | |------|------|------| | Tools | 模型可调用的函数 | 查询订单状态、执行退款 | | Resources | 模型可读取的数据源 | 商品目录、用户手册 | | Prompts | 预定义的提示模板 | 客服话术模板、分析模板 |
- MCP vs Function Calling:
| 维度 | MCP | Function Calling | |------|-----|-----------------| | 层级 | 协议层(标准化通信协议) | 模型层(模型原生能力) | | 耦合度 | 低(客户端与服务器解耦) | 高(函数定义与模型耦合) | | 复用性 | 高(同一MCP Server可服务多个Client) | 低(每个应用单独定义) | | 传输方式 | stdio / SSE / HTTP | API请求内嵌 | | 扩展性 | 高(新增工具只需扩展Server) | 中(需修改应用代码) |
- Spring AI MCP集成示例:
// MCP Client配置
@Bean
public McpSyncClient mcpClient() {
return McpClient.create()
.stdio("java", "-jar", "ecommerce-mcp-server.jar")
.build();
}
// 大模型通过MCP调用工具
String response = chatClient.prompt()
.user("帮我查询订单20240101的物流状态")
.tools(mcpClient) // 注入MCP工具
.call()
.content();
// 模型会自动调用MCP Server暴露的"查询物流"工具
Q12 解析:RAG检索增强生成
业务场景:企业内部知识库(产品文档、FAQ、操作手册)需要智能问答,直接让大模型回答会有幻觉,RAG通过检索真实文档来增强回答准确性。
技术原理:
- RAG完整流程:
【离线阶段 - 文档处理】
文档加载(PDF/Word/HTML) → 文本分块 → 向量化 → 存入向量数据库
【在线阶段 - 检索生成】
用户提问 → 问题向量化 → 向量检索Top-K → 拼接Prompt → LLM生成回答
- 文档分块策略对比:
| 策略 | 描述 | 优点 | 缺点 | |------|------|------|------| | 固定大小分块 | 按token数切分,带重叠 | 实现简单 | 可能切断语义 | | 按段落分块 | 按自然段落切分 | 保留语义完整性 | 段落长度不均 | | 按语义分块 | 用NLP模型识别语义边界 | 语义最完整 | 计算成本高 | | 递归分块 | 先按大段落,再按小段落 | 层次化结构 | 实现复杂 |
- Spring AI RAG实现:
@Configuration
public class RagConfig {
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
return PgVectorStore.builder(jdbcTemplate, embeddingModel)
.dimensions(1536)
.build();
}
@Bean
public QuestionAnswerAdvisor qaAdvisor(VectorStore vectorStore) {
return QuestionAnswerAdvisor.builder(vectorStore)
.promptTemplate("""
基于以下上下文回答问题。如果上下文中没有相关信息,请说"我不知道"。
上下文:
{question_answer_context}
问题:{question_answer_question}
""")
.searchRequest(SearchRequest.builder()
.topK(5) // 检索Top-5相关文档
.similarityThreshold(0.7) // 相似度阈值
.build())
.build();
}
}
// 使用RAG回答问题
String answer = chatClient.prompt()
.user("退货流程是什么?")
.advisors(qaAdvisor) // 注入RAG顾问
.call()
.content();
- 文档加载与处理:
// 加载PDF文档
DocumentReader pdfReader = new PagePdfDocumentReader("product-manual.pdf");
List<Document> documents = pdfReader.get();
// 文本分块
TokenTextSplitter splitter = new TokenTextSplitter();
List<Document> chunks = splitter.split(documents);
// 向量化并存入向量数据库
vectorStore.add(chunks);
Q13 解析:向量数据库选型
业务场景:电商商品库有百万级SKU,用户搜索和推荐需要快速检索相似商品向量。
技术原理:
- 主流向量数据库对比:
| 数据库 | 架构 | 适合规模 | 部署方式 | 特色 | |--------|------|---------|---------|------| | Milvus | 分布式 | 亿级以上 | K8s/集群 | 支持多种索引、标量过滤、分布式检索 | | Chroma | 嵌入式 | 百万级 | 单机 | 轻量级、开箱即用、Python友好 | | Redis | 内存 | 千万级 | 单机/集群 | 混合查询(向量+标量)、利用现有Redis | | PgVector | PostgreSQL扩展 | 千万级 | 单机/集群 | 事务支持、与关系数据联合查询 |
- 向量索引类型对比:
| 索引类型 | 查询速度 | 内存占用 | 精度 | 适用场景 | |---------|---------|---------|------|---------| | FLAT | 慢(暴力搜索) | 低 | 100% | 数据量小,需精确结果 | | IVF_FLAT | 中 | 中 | 高 | 大规模数据,可接受少量误差 | | HNSW | 快 | 高 | 高 | 对查询延迟敏感,内存充足 | | IVF_PQ | 快 | 低 | 中 | 超大规模,可接受精度损失 |
- Milvus索引配置示例:
# Milvus Collection Schema
collection_schema = CollectionSchema([
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
FieldSchema(name="product_name", dtype=DataType.VARCHAR, max_length=256),
FieldSchema(name="price", dtype=DataType.FLOAT)
])
# HNSW索引参数
index_params = {
"index_type": "HNSW",
"metric_type": "COSINE",
"params": {
"M": 16, # 每层最大连接数
"efConstruction": 200 # 构建时搜索宽度
}
}
- Spring AI统一VectorStore抽象:
// 切换向量数据库只需更换实现
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
// 使用Milvus
return MilvusVectorStore.builder(milvusClient, embeddingModel)
.collectionName("products")
.build();
// 或使用Chroma(开发测试环境)
// return ChromaVectorStore.builder(chromaClient, embeddingModel).build();
// 或使用Redis
// return RedisVectorStore.builder(jedis, embeddingModel).build();
}
Q14 解析:Agentic RAG与AI幻觉治理
业务场景:传统RAG只能做单次检索回答,但复杂问题需要多步推理、多轮检索、工具调用。Agentic RAG引入Agent决策层,让AI自主规划检索策略。
技术原理:
- 传统RAG vs Agentic RAG:
【传统RAG流程】
用户提问 → 单次向量检索 → 拼接上下文 → LLM生成 → 返回
(问题:简单问题够用,复杂问题可能检索不到正确信息)
【Agentic RAG流程】
用户提问 → Agent分析问题
├── 判断:是否需要检索?
├── 检索1:向量检索相关文档
├── 判断:信息是否充分?
├── 检索2:调用工具补充信息(如查数据库、调API)
├── 判断:是否需要多轮对话?
├── 推理:综合多源信息
└── 生成:最终回答 + 引用来源
- Agentic RAG核心能力:
| 能力 | 描述 | 技术实现 | |------|------|---------| | 自主决策 | 判断是否检索、检索什么 | LLM作为推理引擎 | | 多轮检索 | 逐步细化检索策略 | Agent循环 + ReAct模式 | | 工具调用 | 调用外部API/数据库 | MCP协议 / Function Calling | | 会话记忆 | 记住上下文进行多轮对话 | ChatMemory | | 引用溯源 | 标注回答来源 | 文档元数据 + 检索得分 |
- Spring AI Agent实现示例:
@Service
public class AgenticRagService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public String answer(String question) {
return chatClient.prompt()
.system("""
你是一个智能助手。请按以下步骤处理用户问题:
1. 分析问题类型
2. 如果需要检索知识库,使用search工具
3. 如果信息不足,可以多次检索
4. 综合检索结果生成回答
5. 标注信息来源
""")
.user(question)
.tools(new SearchTool(vectorStore)) // 自定义检索工具
.advisors(qaAdvisor, chatMemoryAdvisor) // RAG + 记忆
.call()
.content();
}
}
// 自定义工具
public class SearchTool {
private final VectorStore vectorStore;
@Tool(description = "搜索知识库,返回相关文档")
public String searchKnowledgeBase(String query) {
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.builder()
.query(query)
.topK(5)
.build()
);
return docs.stream()
.map(d -> d.getText() + "\n[来源: " + d.getMetadata().get("source") + "]")
.collect(Collectors.joining("\n\n"));
}
}
- AI幻觉治理策略:
| 策略 | 描述 | 效果 | |------|------|------| | RAG上下文约束 | 提供事实文档作为上下文 | ⭐⭐⭐⭐ 显著减少 | | 温度控制 | 降低temperature(如0.1) | ⭐⭐⭐ 减少随机性 | | Prompt约束 | "如不确定请说不知道" | ⭐⭐⭐ 提升诚实度 | | 多路检索交叉验证 | 多次检索对比结果 | ⭐⭐⭐⭐ 提升准确性 | | 引用溯源 | 要求标注信息来源 | ⭐⭐⭐⭐ 可验证性 | | 置信度过滤 | 检索得分低于阈值则拒绝回答 | ⭐⭐⭐⭐ 避免低质量回答 | | 人工审核 | 关键场景人工介入 | ⭐⭐⭐⭐⭐ 最终保障 |
- 完整幻觉治理配置:
String answer = chatClient.prompt()
.system("""
你必须严格遵守以下规则:
1. 只基于提供的上下文回答问题
2. 如果上下文中没有相关信息,回答"根据现有资料,我无法回答这个问题"
3. 每个陈述都必须标注来源文档
4. 不要编造、推测或补充上下文中没有的信息
5. 如果多个来源信息矛盾,请指出矛盾
""")
.user(question)
.advisors(qaAdvisor)
.call()
.content();
// 后置检查:验证回答中是否包含引用
if (!answer.contains("[来源:")) {
log.warn("回答缺少引用来源,可能存在幻觉风险: {}", answer);
}
📊 技术栈覆盖总结
| 轮次 | 场景 | 涉及技术栈 | |------|------|-----------| | 第1轮 | 电商场景 | Spring Boot, Maven, Java 17, MyBatis, JPA, HikariCP, Flyway, Redis, Spring Cache, Kafka, Jackson | | 第2轮 | 微服务云原生 | Spring Cloud, Nacos, OpenFeign, Resilience4j, gRPC, Protobuf, Docker, Kubernetes, Helm, Istio, Prometheus, Grafana, Micrometer, Jaeger, Spring Cloud Sleuth | | 第3轮 | AI与大数据 | Spring AI, MCP协议, RAG, Agent, ChatClient, EmbeddingModel, VectorStore, ChatMemory, Milvus, Chroma, Redis, PgVector, HNSW/IVF索引, Protobuf, Elasticsearch |
💡 学习建议:本文覆盖了从传统Java Web到AI时代的前沿技术栈。建议初学者先掌握第1轮的基础技术(Spring Boot + Redis + Kafka),再学习第2轮的微服务架构,最后探索第3轮的AI技术。技术是循序渐进的,每一步都打牢基础,才能在面试中游刃有余。
本文由AI生成,技术内容基于公开资料和最佳实践整理,如有疑问欢迎交流讨论。
更多推荐

所有评论(0)