大厂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的默认策略嘛……maxSurgemaxUnavailable配置一下……回滚就是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依赖机制大幅提升开发效率。

技术原理

  1. Maven构建:通过继承spring-boot-starter-parent获得统一的依赖版本管理:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
</parent>
  1. Java 17升级注意事项

    • Spring Boot 3.x 最低要求Java 17
    • javax.* 包替换为 jakarta.*(Jakarta EE迁移)
    • 需要检查第三方依赖是否兼容Java 17
    • Records、密封类、模式匹配等新特性可用
  2. 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。

技术原理

  1. MyBatis vs JPA选型

| 维度 | MyBatis | JPA/Hibernate | |------|---------|---------------| | SQL控制 | 完全控制,手写SQL | 自动生成,JPQL/HQL | | 学习成本 | 低,会SQL即可 | 高,需理解实体关系映射 | | 复杂查询 | 优秀,支持动态SQL | 较弱,复杂查询需写原生SQL | | 开发效率 | 中等,需写XML/注解 | 高,自动生成CRUD | | 适用场景 | 商品列表、报表查询 | 订单、用户等实体关系复杂场景 |

  1. HikariCP连接池核心配置
spring:
  datasource:
    hikari:
      maximum-pool-size: 20        # 最大连接数
      minimum-idle: 5              # 最小空闲连接
      connection-timeout: 30000    # 连接超时(ms)
      idle-timeout: 600000         # 空闲超时(ms)
      max-lifetime: 1800000        # 连接最大生命周期(ms)
  1. 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缓存。

技术原理

  1. 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" |

  1. 缓存一致性 —— Cache Aside模式
读操作:先查缓存 → 命中则返回 → 未命中则查DB → 写入缓存 → 返回
写操作:更新数据库 → 删除缓存
  1. 三大缓存问题及解决方案

| 问题 | 描述 | 解决方案 | |------|------|---------| | 缓存穿透 | 查询不存在的数据,缓存和DB都没有 | 布隆过滤器 + 缓存空值 | | 缓存击穿 | 热点key过期,大量请求穿透到DB | 互斥锁 + 热点key永不过期 | | 缓存雪崩 | 大量key同时过期 | 随机过期时间 + 多级缓存 |

  1. 布隆过滤器代码示例
// 使用Redisson实现布隆过滤器
RBloomFilter<Long> bloomFilter = redisson.getBloomFilter("product:exist");
bloomFilter.tryInit(1000000L, 0.01); // 预计100万数据,误判率1%

// 查询时先过布隆过滤器
if (!bloomFilter.contains(productId)) {
    return null; // 商品一定不存在
}

Q4 解析:Kafka异步消息处理与可靠性保证

业务场景:电商下单流程中,创建订单后需要扣库存、加积分、发通知。同步处理导致接口耗时过长,用Kafka异步解耦。

技术原理

  1. Kafka架构核心概念
Producer → Topic (Partition) → Consumer Group
                              ├── Consumer 1 (库存服务)
                              ├── Consumer 2 (积分服务)
                              └── Consumer 3 (通知服务)
  1. 消息不丢失的三个层面

| 层面 | 配置 | 说明 | |------|------|------| | Producer端 | acks=all + retries=3 | 等待所有副本确认,失败自动重试 | | Broker端 | min.insync.replicas=2 | 至少2个副本同步成功 | | Consumer端 | enable.auto.commit=false | 手动提交offset,处理完再提交 |

  1. 消息幂等性保证
// 方案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);
  1. 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 解析:服务注册发现

业务场景:微服务拆分后,服务实例动态扩缩容,需要服务注册中心自动发现实例地址。

技术原理

  1. Nacos vs Eureka对比

| 维度 | Nacos | Eureka | |------|-------|--------| | 一致性协议 | Raft (CP) + Distro (AP) | AP (最终一致性) | | 配置中心 | 内置支持 | 不支持 | | 健康检查 | TCP/HTTP/自定义 | 心跳 | | 服务推送 | 主动推送变更 | 客户端轮询 | | 维护状态 | 活跃维护 | 2.x停止维护 |

  1. 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熔断降级

业务场景:大促期间库存服务负载过高,响应变慢,需要熔断保护订单服务不被级联拖垮。

技术原理

  1. Resilience4j核心组件

| 组件 | 功能 | 应用场景 | |------|------|---------| | CircuitBreaker | 熔断器 | 防止级联故障 | | Bulkhead | 舱壁隔离 | 限制并发调用数 | | RateLimiter | 限流 | 控制请求速率 | | Retry | 重试 | 临时故障自动恢复 | | TimeLimiter | 超时控制 | 防止长时间等待 |

  1. 熔断器状态机
CLOSED ──(失败率≥阈值)──> OPEN ──(等待时间结束)──> HALF_OPEN
  ↑                                                    │
  └──────────(探测成功)────────────────────────────────┘
                                    │
                              (探测失败)
                                    ↓
                                  OPEN
  1. 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探测次数
  1. 代码使用
@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更适合。

技术原理

  1. gRPC vs REST对比

| 维度 | gRPC | REST | |------|------|------| | 协议 | HTTP/2 | HTTP/1.1 | | 序列化 | Protobuf(二进制) | JSON(文本) | | 性能 | 高(序列化快、体积小) | 中 | | 流式支持 | 双向流 | 不支持(需WebSocket) | | 可读性 | 低(二进制) | 高(JSON可读) | | 浏览器支持 | 需gRPC-Web | 原生支持 | | 适用场景 | 内部服务高频调用 | 对外API、低频调用 |

  1. 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;
}
  1. Protobuf版本兼容性原则
  • 新增字段:使用新字段编号,不影响旧版本解析
  • 删除字段:使用reserved关键字保留编号,避免复用
  • 字段类型变更:不兼容,需要新字段编号

Q8 解析:Kubernetes部署与CI/CD

业务场景:微服务需要容器化部署,实现弹性伸缩和滚动更新。

技术原理

  1. CI/CD完整流程
开发提交代码 → GitLab Pipeline触发
  ├── 阶段1: 编译打包 (mvn clean package)
  ├── 阶段2: 单元测试 (JUnit 5 + Mockito)
  ├── 阶段3: 构建Docker镜像 (docker build)
  ├── 阶段4: 推送镜像仓库 (docker push)
  └── 阶段5: 部署K8s (helm upgrade)
  1. 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"]
  1. 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
  1. 金丝雀发布(通过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个服务,需要全链路监控和追踪。

技术原理

  1. 监控体系架构
Spring Boot Actuator
    └── Micrometer (指标抽象层)
         └── Prometheus (指标存储)
              └── Grafana (可视化看板)

Spring Cloud Sleuth / Micrometer Tracing
    └── Jaeger / Zipkin (分布式链路追踪)
  1. 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>
  1. application.yml配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,metrics
  metrics:
    tags:
      application: order-service
  tracing:
    sampling:
      probability: 1.0  # 采样率,生产环境建议0.1
  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智能客服,自动回答用户关于商品、订单、退换货的问题。

技术原理

  1. Spring AI核心架构
Spring AI
├── ChatClient        → 对话生成(接OpenAI/Ollama/Azure等)
├── EmbeddingModel    → 文本向量化
├── VectorStore       → 向量存储抽象(Milvus/Chroma/Redis等)
├── ChatMemory        → 会话记忆管理
└── Advisors          → 顾问链(RAG、日志、安全等)
  1. 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();
    }
}
  1. 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();
    }
}
  1. 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协议标准化这些工具的接入方式。

技术原理

  1. MCP架构
┌─────────────────┐     MCP协议      ┌─────────────────┐
│   MCP Client    │ ←──────────────→ │   MCP Server    │
│  (Spring AI App) │                  │  (工具提供方)    │
│                 │                  │                 │
│  - 发起工具调用   │                  │  - 暴露Tools     │
│  - 管理会话      │                  │  - 暴露Resources │
│  - 处理响应      │                  │  - 暴露Prompts   │
└─────────────────┘                  └─────────────────┘
  1. MCP三大核心组件

| 组件 | 功能 | 示例 | |------|------|------| | Tools | 模型可调用的函数 | 查询订单状态、执行退款 | | Resources | 模型可读取的数据源 | 商品目录、用户手册 | | Prompts | 预定义的提示模板 | 客服话术模板、分析模板 |

  1. MCP vs Function Calling

| 维度 | MCP | Function Calling | |------|-----|-----------------| | 层级 | 协议层(标准化通信协议) | 模型层(模型原生能力) | | 耦合度 | 低(客户端与服务器解耦) | 高(函数定义与模型耦合) | | 复用性 | 高(同一MCP Server可服务多个Client) | 低(每个应用单独定义) | | 传输方式 | stdio / SSE / HTTP | API请求内嵌 | | 扩展性 | 高(新增工具只需扩展Server) | 中(需修改应用代码) |

  1. 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通过检索真实文档来增强回答准确性。

技术原理

  1. RAG完整流程
【离线阶段 - 文档处理】
文档加载(PDF/Word/HTML) → 文本分块 → 向量化 → 存入向量数据库

【在线阶段 - 检索生成】
用户提问 → 问题向量化 → 向量检索Top-K → 拼接Prompt → LLM生成回答
  1. 文档分块策略对比

| 策略 | 描述 | 优点 | 缺点 | |------|------|------|------| | 固定大小分块 | 按token数切分,带重叠 | 实现简单 | 可能切断语义 | | 按段落分块 | 按自然段落切分 | 保留语义完整性 | 段落长度不均 | | 按语义分块 | 用NLP模型识别语义边界 | 语义最完整 | 计算成本高 | | 递归分块 | 先按大段落,再按小段落 | 层次化结构 | 实现复杂 |

  1. 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();
  1. 文档加载与处理
// 加载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,用户搜索和推荐需要快速检索相似商品向量。

技术原理

  1. 主流向量数据库对比

| 数据库 | 架构 | 适合规模 | 部署方式 | 特色 | |--------|------|---------|---------|------| | Milvus | 分布式 | 亿级以上 | K8s/集群 | 支持多种索引、标量过滤、分布式检索 | | Chroma | 嵌入式 | 百万级 | 单机 | 轻量级、开箱即用、Python友好 | | Redis | 内存 | 千万级 | 单机/集群 | 混合查询(向量+标量)、利用现有Redis | | PgVector | PostgreSQL扩展 | 千万级 | 单机/集群 | 事务支持、与关系数据联合查询 |

  1. 向量索引类型对比

| 索引类型 | 查询速度 | 内存占用 | 精度 | 适用场景 | |---------|---------|---------|------|---------| | FLAT | 慢(暴力搜索) | 低 | 100% | 数据量小,需精确结果 | | IVF_FLAT | 中 | 中 | 高 | 大规模数据,可接受少量误差 | | HNSW | 快 | 高 | 高 | 对查询延迟敏感,内存充足 | | IVF_PQ | 快 | 低 | 中 | 超大规模,可接受精度损失 |

  1. 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  # 构建时搜索宽度
    }
}
  1. 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自主规划检索策略。

技术原理

  1. 传统RAG vs Agentic RAG
【传统RAG流程】
用户提问 → 单次向量检索 → 拼接上下文 → LLM生成 → 返回
(问题:简单问题够用,复杂问题可能检索不到正确信息)

【Agentic RAG流程】
用户提问 → Agent分析问题
  ├── 判断:是否需要检索?
  ├── 检索1:向量检索相关文档
  ├── 判断:信息是否充分?
  ├── 检索2:调用工具补充信息(如查数据库、调API)
  ├── 判断:是否需要多轮对话?
  ├── 推理:综合多源信息
  └── 生成:最终回答 + 引用来源
  1. Agentic RAG核心能力

| 能力 | 描述 | 技术实现 | |------|------|---------| | 自主决策 | 判断是否检索、检索什么 | LLM作为推理引擎 | | 多轮检索 | 逐步细化检索策略 | Agent循环 + ReAct模式 | | 工具调用 | 调用外部API/数据库 | MCP协议 / Function Calling | | 会话记忆 | 记住上下文进行多轮对话 | ChatMemory | | 引用溯源 | 标注回答来源 | 文档元数据 + 检索得分 |

  1. 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"));
    }
}
  1. AI幻觉治理策略

| 策略 | 描述 | 效果 | |------|------|------| | RAG上下文约束 | 提供事实文档作为上下文 | ⭐⭐⭐⭐ 显著减少 | | 温度控制 | 降低temperature(如0.1) | ⭐⭐⭐ 减少随机性 | | Prompt约束 | "如不确定请说不知道" | ⭐⭐⭐ 提升诚实度 | | 多路检索交叉验证 | 多次检索对比结果 | ⭐⭐⭐⭐ 提升准确性 | | 引用溯源 | 要求标注信息来源 | ⭐⭐⭐⭐ 可验证性 | | 置信度过滤 | 检索得分低于阈值则拒绝回答 | ⭐⭐⭐⭐ 避免低质量回答 | | 人工审核 | 关键场景人工介入 | ⭐⭐⭐⭐⭐ 最终保障 |

  1. 完整幻觉治理配置
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生成,技术内容基于公开资料和最佳实践整理,如有疑问欢迎交流讨论。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐