Spring Boot 3.x + 微服务速查手册(2026 面试版)

最后更新:2026-08-10

本手册面向 Java 高级开发工程师面试,覆盖 Spring Boot 3.x 核心特性、微服务架构设计与治理实战。 风格:说人话、给话术、上案例,不搞照本宣科。


目录

  1. Spring Boot 3.x 核心变化

  2. 自动装配原理

  3. Spring Boot 启动流程

  4. 微服务架构设计

  5. 服务治理实战

  6. 分布式事务

  7. 微服务监控与运维

  8. Spring Boot 3.x + AI 集成

  9. 面试高频问答


1. Spring Boot 3.x 核心变化

1.1 一句话概括

Spring Boot 3.x = JDK 17 起步 + Jakarta EE 全面替换 + 云原生优先(Native Image) + 可观测性内置

1.2 关键变化一览

变化点Spring Boot 2.xSpring Boot 3.x面试要点
JDK 最低版本JDK 8JDK 17(推荐 JDK 21)虚拟线程(Virtual Thread)JDK 21 才支持
Java EE 包名javax.*jakarta.*不是简单换包名,涉及大量第三方库适配
Native Image不支持支持 GraalVM Native Image启动时间从秒级到毫秒级,内存省 70%+
AOT 编译有 AOT Processing编译期生成 BeanDefinition,减少反射开销
可观测性需要自己集成Micrometer Observation API 内置统一 Metrics + Tracing + Logging
SecurityWebSecurityConfigurerAdapter基于组件式 SecurityFilterChain老写法直接删了,新写法用 Bean 注入
自动装配注册spring.factoriesAutoConfiguration.imports3.x 两种方式都兼容,但推荐新方式
HTTP ClientRestTemplate 为主推荐 RestClient / HTTP Interface ClientRestClient 是 3.2 新增的流式 API

1.3 JDK 21 虚拟线程实战

# application.yml
spring:
  threads:
    virtual:
      enabled: true  # 一行配置开启虚拟线程

面试怎么说:「Spring Boot 3.2 开始支持虚拟线程,我们项目从 JDK 17 升到了 21,开启虚拟线程后,Tomcat 线程池从 200 缩减到 50,但并发能力提升了一倍多。核心原因是虚拟线程在 IO 阻塞时会自动让出载体线程,特别适合我们这种 IO 密集型的微服务场景。」

1.4 Jakarta EE 迁移踩坑

真实踩坑场景

  • 用了老版本 MyBatis-Plus(3.5.x 以下),启动直接报 ClassNotFoundException: javax.servlet.Filter

  • Swagger(SpringFox)不兼容了,要换成 SpringDoc(springdoc-openapi-starter-webmvc-ui

  • @Validatedjavax.validation 变成 jakarta.validation

迁移口诀javax 换 jakarta,插件帮你批量改,SpringFox 换 SpringDoc,Hibernate Validator 升 8.x

1.5 Native Image 实战数据

指标JVM 模式Native Image
启动时间2.3s0.08s
内存占用320MB85MB
打包时间-约 3-5 分钟
反射支持完整需要手动注册(reflect-config.json)

面试怎么说:「我们有两个服务做了 Native Image,一个是网关,一个是 BFF 层。网关启动从 8 秒降到 80 毫秒,在 K8s 里弹性扩缩容速度非常快。但要注意,Native Image 不支持动态类加载,像 CGLIB 动态代理这类需要编译期处理,所以不是所有服务都适合做 Native。」


2. 自动装配原理

2.1 一句话原理

自动装配 = 条件装配 + SPI 机制 + 约定大于配置。 Spring Boot 启动时扫描所有 jar 包里的自动配置类,按条件判断要不要生效。

2.2 装配链路(3.x 新版)

@SpringBootApplication
  └── @EnableAutoConfiguration
        └── @Import(AutoConfigurationImportSelector.class)
              └── 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
                    └── 每行一个自动配置类全限定名
                          └── 按 @Conditional 系列注解判断是否生效

2.x vs 3.x 区别

2.x3.x
配置文件META-INF/spring.factoriesMETA-INF/spring/...AutoConfiguration.imports
格式key=value(EnableAutoConfiguration=类名)每行一个类名,简单直接
向后兼容-3.x 仍然兼容 spring.factories,但推荐新方式

2.3 核心条件注解速查

注解含义使用场景
@ConditionalOnClassclasspath 下有某个类才生效引入了某个 starter 才生效
@ConditionalOnMissingBean容器里没有某个 Bean 才创建用户没自定义就用默认的
@ConditionalOnProperty配置文件满足某个属性开关控制
@ConditionalOnWebApplication是 Web 应用才生效Web 专属配置
@ConditionalOnMissingClassclasspath 下没有某个类和 OnClass 配合做互斥

2.4 自定义 Starter 完整流程

场景:公司要统一日志格式(加 traceId、env、app_name),做一个 company-log-spring-boot-starter

company-log-spring-boot-starter/
├── pom.xml
└── src/main/java/com/company/log/
    ├── CompanyLogAutoConfiguration.java   // 自动配置类
    ├── CompanyLogProperties.java          // 配置属性类
    └── CompanyLogFilter.java             // 核心逻辑(Filter/Interceptor)
└── src/main/resources/
    └── META-INF/spring/
        └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

核心代码

@ConfigurationProperties(prefix = "company.log")
public class CompanyLogProperties {
    private boolean enabled = true;
    private String format = "json"; // json / text
    // getter/setter
}

@AutoConfiguration
@ConditionalOnClass(CompanyLogFilter.class)
@ConditionalOnProperty(prefix = "company.log", name = "enabled",
    havingValue = "true", matchIfMissing = true)
public class CompanyLogAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public CompanyLogFilter companyLogFilter(CompanyLogProperties properties) {
        return new CompanyLogFilter(properties);
    }
}

imports 文件内容:

com.company.log.CompanyLogAutoConfiguration

面试怎么说:「我们做了 20+ 个内部 starter,比如统一鉴权、统一日志、分布式 ID、灰度路由。套路都一样:一个 Properties 类管配置,一个 AutoConfiguration 类管装配,条件注解控制生效时机。关键是 @ConditionalOnMissingBean,这样业务方如果有定制需求,自己定义一个 Bean 就能覆盖默认实现。」


3. Spring Boot 启动流程

3.1 SpringApplication.run() 核心流程

1. new SpringApplication()
   ├── 推断应用类型(SERVLET / REACTIVE / NONE)
   ├── 加载 ApplicationContextInitializer(从 spring.factories)
   ├── 加载 ApplicationListener(从 spring.factories)
   └── 推断主启动类

2. run(args)
   ├── 创建并启动 Environment(加载配置文件)
   ├── 创建 ApplicationContext
   ├── 执行 Initializer.initialize()
   ├── 注册 Listener
   ├── 执行 run() → 核心:refreshContext()(Spring 容器启动)
   ├── 执行 Runner.run()(CommandLineRunner / ApplicationRunner)
   └── 发布 ApplicationReadyEvent

3.2 关键扩展点

扩展点时机典型用途
ApplicationContextInitializer容器 refresh 之前加环境变量、改配置源
ApplicationListener各阶段事件监听启动耗时统计、预热缓存
ApplicationRunner / CommandLineRunner容器完全启动后数据初始化、任务调度启动
ApplicationStartup启动过程埋点Spring Startup Actuator 查看启动耗时

3.3 Bean 生命周期(简化版 — 面试够用了)

实例化(Instantiation)
  → 属性填充(Populate,依赖注入)
    → Aware 回调(BeanNameAware、BeanFactoryAware 等)
      → BeanPostProcessor.postProcessBeforeInitialization()
        → @PostConstruct / InitializingBean.afterPropertiesSet()
          → BeanPostProcessor.postProcessAfterInitialization()(AOP 代理在这里创建)
            → 使用中...
              → @PreDestroy / DisposableBean.destroy()

口诀实例化 → 注入 → Aware → Before → 初始化 → After → 使用 → 销毁

3.4 循环依赖

经典三级缓存(Spring 6 / Boot 3 之前):

缓存作用
singletonObjects(一级)完整 Bean
earlySingletonObjects(二级)早期暴露的 Bean(可能还没属性填充)
singletonFactories(三级)Bean 的 ObjectFactory(用于创建代理对象)

Spring Boot 2.6+ / 3.x 变化

  • 默认禁止循环依赖!启动直接报错。

  • 需要手动开启:spring.main.allow-circular-references=true(生产环境不推荐)

  • 正确做法:重构代码,用 @Lazy 或提取公共 Bean 来打破循环

面试怎么说:「Spring Boot 3.x 默认不允许循环依赖,这是一个设计信号——循环依赖说明你的模块划分有问题。我们项目里遇到循环依赖,一般两种解法:一是用 @Lazy 延迟注入;二是重构,把互相依赖的逻辑抽到一个中间服务里。如果是构造器注入的循环依赖,那只能用 @Lazy 或者改成 setter 注入了。」


4. 微服务架构设计

4.1 服务拆分原则

一句话:按业务边界拆,不按技术层拆。

DDD 战略设计四步法

  1. 事件风暴:梳理业务领域事件

  2. 统一语言:和产品对齐术语(不要一个东西三个名)

  3. 限界上下文:划定服务边界

  4. 上下文映射:定义服务间关系(防腐层、开放主机服务等)

拆分反模式

反模式问题正确做法
按技术层拆(User-API、User-Service、User-DAO)一个需求改三个服务按业务领域拆
拆太细(一个 CRUD 一个服务)运维成本爆炸合理聚合
共享数据库改表全链路崩溃每个服务独立数据库

4.2 服务间通信方式对比

方式协议性能适用场景典型技术
REST/HTTPHTTP/1.1 或 2中等对外 API、简单调用Spring WebFlux / RestClient
gRPCHTTP/2 + Protobuf极高内部高频调用、流式传输grpc-spring-boot-starter
消息队列TCP异步解耦削峰、最终一致性、事件驱动RocketMQ Kafka Pulsar
GraphQLHTTP中等BFF 层、前端灵活查询spring-graphql

选型口诀同步低延迟选 gRPC,简单好调试选 REST,异步解耦选 MQ,前端灵活查选 GraphQL

4.3 API 网关设计(Spring Cloud Gateway)

核心功能

  • 路由转发

  • 鉴权(JWT 校验)

  • 限流(RequestRateLimiter + Redis)

  • 灰度发布(权重路由)

  • 日志 & 链路追踪

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100
                redis-rate-limiter.burstCapacity: 200

网关设计要点

  • 网关不处理业务逻辑,只做路由和横切关注点

  • 鉴权放网关,但细粒度权限放各服务

  • 网关要做限流,不然一波流量直接把后端打挂

  • 网关本身要无状态,方便水平扩展

4.4 服务注册发现(Nacos)

spring:
  cloud:
    nacos:
      discovery:
        server-addr: nacos:8848
        namespace: dev
        group: DEFAULT_GROUP

Nacos vs Eureka vs Consul

特性NacosEurekaConsul
健康检查TCP/HTTP/MySQL/自定义心跳TCP/HTTP/gRPC
配置中心内置不支持支持
负载均衡权重区域多策略
跨数据中心支持不支持支持
CAP 模型AP + CP 可切换APCP

面试怎么说:「我们用 Nacos 做注册中心 + 配置中心,一个组件解决两个问题。Nacos 支持 AP 和 CP 模式切换——临时实例走 AP(适合大部分微服务),持久化实例走 CP(适合 DNS/网关路由这种不能丢的)。而且 Nacos 的权重路由功能,在灰度发布时非常有用。」

4.5 配置中心(Nacos Config)

配置优先级(从高到低):

  1. Nacos 指定 profile 配置(app-dev.yaml

  2. Nacos 默认配置(app.yaml

  3. 本地 application-{profile}.yaml

  4. 本地 application.yaml

动态刷新

@RefreshScope  // 加了这个注解,配置变更时 Bean 自动重建
@RestController
public class ConfigController {
    @Value("${feature.new-ui.enabled:false}")
    private boolean newUiEnabled;
}

4.6 链路追踪(Micrometer + OpenTelemetry)

Spring Boot 3.x 用 Micrometer Tracing 替代了之前的 Spring Cloud Sleuth。

management:
  tracing:
    sampling:
      probability: 1.0  # 采样率(生产建议 0.1 = 10%)
  otlp:
    tracing:
      endpoint: http://otel-collector:4318/v1/traces

面试怎么说:「我们链路追踪用的是 OpenTelemetry + Jaeger,Spring Boot 3.x 原生支持 Micrometer Tracing,只需要引入 micrometer-tracing-bridge-otelopentelemetry-exporter-otlp 两个依赖,配置一下 endpoint 就行了。traceId 会自动在日志里打印,排查问题的时候 grep 一下就能把整条链路串起来。」


5. 服务治理实战

5.1 限流:Sentinel 实战

四种流控效果

效果说明场景
Quick Fail(快速失败)超过阈值直接拒绝最常用,简单粗暴
Warm Up(预热)慢慢增加通过的 QPS防止冷启动流量冲击
Rate Limiter(匀速排队)漏桶算法,匀速处理保护下游慢服务
Warm Up + 排队预热 + 排队大促开场
@SentinelResource(value = "getOrder",
    blockHandler = "getOrderBlock",      // 限流/降级处理
    fallback = "getOrderFallback")       // 异常兜底
@GetMapping("/order/{id}")
public Order getOrder(@PathVariable Long id) {
    return orderService.getById(id);
}

// 限流时调用
public Order getOrderBlock(Long id, BlockException ex) {
    return Order.empty(); // 返回降级数据
}

// 异常时调用
public Order getOrderFallback(Long id, Throwable ex) {
    log.error("查询订单异常", ex);
    return Order.cached(id); // 返回缓存兜底
}

5.2 熔断降级

Sentinel 熔断策略

策略触发条件说明
慢调用比例响应时间 > 阈值的请求比例过高适合保护慢下游
异常比例异常请求比例过高适合下游不稳定场景
异常数异常数超过阈值简单粗暴

实战建议

  • 慢调用阈值设为正常 RT 的 2-3 倍

  • 熔断时间先设 10s,观察调整后固定

  • Fallback 不要返回 null,返回缓存数据或默认值

  • 核心链路和非核心链路分开降级

5.3 负载均衡策略

策略说明适用场景
RoundRobin轮询服务实例配置相同
Random随机简单场景
Weighted权重灰度发布、机器配置不同
LeastActive最少活跃调用数服务处理能力差异大
ConsistentHash一致性哈希有缓存场景(相同请求到同一实例)

5.4 重试机制设计

原则

  • 只对 读操作幂等写操作 重试

  • 最大重试次数退避策略

  • 重试要带 超时,防止雪崩

spring:
  retry:
    template:
      max-attempts: 3
      backoff:
        initial-interval: 1000
        multiplier: 2  # 指数退避:1s - 2s - 4s
        max-interval: 10000

5.5 幂等性保证方案

方案原理适用场景优点缺点
Token 机制先获取 token,提交时携带,用完即焚表单提交、支付简单可靠多一次网络请求
数据库唯一键INSERT 时用唯一索引防重复创建订单最简单只能防数据库层面
Redis SETNX用请求 ID 做 key,设过期时间通用场景性能好Redis 挂了要兜底
状态机状态只能单向流转订单、审批业务层面保证要设计好状态图

面试怎么说:「支付回调幂等我们用了两层保证:第一层 Redis SETNX,key 是 pay_notify:{tradeNo},5 分钟过期;第二层数据库唯一索引 uk_trade_no。Redis 成功了就直接返回,Redis 挂了还有数据库兜底。状态机方面,订单状态只能单向流转(待支付 - 已支付 - 已发货),反向操作直接拒绝。」


6. 分布式事务

6.1 方案对比

方案一致性性能复杂度适用场景
2PC(强一致)强一致低(锁资源时间长)银行转账、金融核心
TCC最终一致极高(要写三个接口)资金、库存等核心场景
SAGA最终一致长事务、跨多个服务
本地消息表最终一致异步解耦、对实时性要求不高
消息事务(RocketMQ)最终一致订单 + 库存 + 积分这类
Seata AT最终一致低(框架帮你做)中小项目、快速落地

6.2 Seata AT 模式原理

1. TM(事务管理器)开启全局事务,获取 XID
2. RM(资源管理器)执行本地 SQL 前:
   - 解析 SQL,生成"前镜像"(before image)
   - 执行 SQL
   - 生成"后镜像"(after image)
   - 将两个镜像写入 undo_log 表
   - 提交本地事务
3. 如果所有分支成功 → TC 通知删除 undo_log
4. 如果某个分支失败 → TC 通知回滚,用 undo_log 反向补偿

优点:业务无侵入(只需加 @GlobalTransactional 注解) 缺点:依赖全局锁,高并发下性能有瓶颈

6.3 实战选型指南

场景判断树:
├── 金融核心场景?
│   ├── 是 → TCC(自己控制 Try/Confirm/Cancel)
│   └── 否 ↓
├── 并发量高(>5000 QPS)?
│   ├── 是 → 消息队列(RocketMQ 事务消息)
│   └── 否 ↓
├── 团队小、想快速落地?
│   ├── 是 → Seata AT
│   └── 否 ↓
└── 其他 → 本地消息表 / SAGA

面试怎么说:「我们电商项目的下单流程用的是 RocketMQ 事务消息。下单时先发半消息,然后执行本地订单创建,成功后提交消息,库存服务和积分服务消费消息做各自的事情。如果本地事务失败了,半消息回滚,下游不会收到消息。这种方式吞吐量高,而且下游服务可以独立重试。对于支付这种强一致性要求高的场景,用的是 TCC 模式。」


7. 微服务监控与运维

7.1 监控四根支柱

支柱工具关注什么
健康检查Spring Actuator服务活着没
日志ELK / Loki + Grafana发生了什么
指标Prometheus + Grafana性能怎么样
链路OpenTelemetry + Jaeger/Tempo请求去了哪里

7.2 健康检查(Actuator)

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,metrics
  endpoint:
    health:
      show-details: always

自定义健康指标

@Component
public class RedisHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        try {
            redisTemplate.opsForValue().get("health:check");
            return Health.up().withDetail("redis", "available").build();
        } catch (Exception e) {
            return Health.down().withException(e).build();
        }
    }
}

7.3 日志收集

推荐架构应用日志 → Filebeat/Fluentd → Kafka → Elasticsearch/Loki → Grafana

日志规范

  • 必须包含 traceIdspanId

  • JSON 格式(方便 ELK 解析)

  • 敏感信息脱敏

  • 不同级别分文件(INFO WARN ERROR)

7.4 指标监控

关键指标

类别指标告警阈值(参考)
JVM堆内存使用率> 80%
JVMGC 频率Full GC > 1次/小时
HTTPP99 延迟> 500ms
HTTP5xx 错误率> 1%
系统CPU 使用率> 70%
线程池队列堆积量> 80%
连接池活跃连接数> 80% 最大连接数

7.5 告警方案设计

告警分级:
├── P0(立即处理):服务挂了、核心接口全挂、数据库连接池满
├── P1(5分钟内处理):错误率 > 5%、延迟 P99 > 2s
├── P2(30分钟内处理):磁盘 > 80%、GC 频率异常
└── P3(工作时间处理):非核心服务异常、慢 SQL

面试怎么说:「我们监控体系是 Prometheus + Grafana + AlertManager。Prometheus 负责采集指标,Grafana 做可视化大盘,AlertManager 负责告警路由。告警分级管理,P0 级走电话 + 钉钉群,P1 级钉钉通知,P2/P3 级邮件。关键是要有告警收敛,不然一波告警风暴根本看不过来。」


8. Spring Boot 3.x + AI 集成

8.1 Spring AI 框架概述

Spring AI 是 Spring 官方的 AI 集成框架(2023 年底开始,2024-2025 快速迭代),目标是让 AI 集成像 Spring 集成数据库一样简单。

核心抽象

接口作用类比
ChatClient调用大模型对话RestTemplate
ChatModel模型实现(OpenAI/Ollama/通义等)DataSource
EmbeddingModel文本向量化用于 RAG
VectorStore向量存储Redis/PG/Milvus
FunctionCallbackFunction Calling让模型调用你的代码

8.2 集成 OpenAI / 本地模型

# 接 OpenAI(或兼容 API,如通义千问、DeepSeek)
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      base-url: https://api.deepseek.com  # 换地址就能接国产模型
      chat:
        options:
          model: deepseek-chat
          temperature: 0.7

# 接本地模型(Ollama)
spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:14b

8.3 RAG 模式实现

RAG = 检索增强生成,让大模型基于你的私有数据回答问题。

流程:
1. 文档 → 切分(Chunk)→ Embedding → 存入 VectorStore
2. 用户提问 → Embedding → 从 VectorStore 检索 Top-K 相关片段
3. 将检索片段 + 用户问题 → 拼成 Prompt → 发给大模型
4. 返回回答
@Service
public class RagService {
    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public String ask(String question) {
        // 1. 检索相关文档
        List<Document> docs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(5)
        );
        String context = docs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("
---
"));

        // 2. 构造 Prompt
        String systemPrompt = "基于以下参考资料回答问题。如果资料中没有相关信息,请说明。";
        String userPrompt = "参考资料:
" + context + "

问题:" + question;

        // 3. 调用模型
        return chatClient.prompt()
            .system(systemPrompt)
            .user(userPrompt)
            .call()
            .content();
    }
}

8.4 Function Calling

让大模型能调用你的业务方法。

// 定义函数
@Bean
public FunctionCallback weatherFunctionCallback() {
    return FunctionCallback.builder()
        .function("getWeather", (WeatherRequest req) ->
            weatherService.getWeather(req.city()))
        .description("获取指定城市的天气信息")
        .inputType(WeatherRequest.class)
        .build();
}

// 使用
String response = chatClient.prompt()
    .user("北京今天天气怎么样?")
    .functions("getWeather")  // 告诉模型可以调用这个函数
    .call()
    .content();
// 模型会自动调用 getWeather("北京"),然后基于结果生成回答

面试怎么说:「我们在内部知识问答系统里用了 Spring AI + RAG。文档先做切分(500 token 一个 chunk),用 BGE 模型做 embedding,存在 Milvus 里。用户提问时检索 Top 5 相关片段,拼成 prompt 发给大模型。效果比纯模型回答准确率提升了 40%。另外 Function Calling 用在了智能客服里,模型可以调用订单查询、物流查询这些函数,用户说'我的快递到哪了',模型自动调用物流查询接口。」


9. 面试高频问答

Q1:Spring Boot 和 Spring 有什么区别?

回答:「Spring 是框架,Spring Boot 是脚手架。Spring 需要大量 XML 配置,Boot 用约定大于配置,内嵌 Tomcat,开箱即用。Spring Boot 不是替代 Spring,是让你更快用 Spring。」

Q2:@SpringBootApplication 包含了什么?

回答:「三个注解的组合:@SpringBootConfiguration(本质是 @Configuration)、@EnableAutoConfiguration(开启自动装配)、@ComponentScan(组件扫描)。其中 @EnableAutoConfiguration 是核心,它通过 ImportSelector 读取 SPI 配置加载所有自动配置类。」

Q3:Spring Boot 配置文件加载优先级?

回答:「命令行参数 > 系统环境变量 > application-{profile}.yaml > application.yaml > @PropertySource 注解。实际生产中,我们用 Nacos 配置中心覆盖本地配置,优先级:Nacos 指定 profile > Nacos 默认 > 本地 profile > 本地默认。」

Q4:如何实现 Spring Boot 项目的热部署?

回答:「开发环境用 spring-boot-devtools,改完代码自动重启。生产环境不存在热部署,都是 CI/CD + 滚动更新。JRebel 也行但收费。」

Q5:Spring Boot 如何处理异常?

回答:「统一异常处理:@RestControllerAdvice + @ExceptionHandler。全局捕获异常,返回统一格式 {code, message, data}。关键异常要记日志,业务异常不记 error(记 warn),系统异常记 error + 告警。」

Q6:Spring Boot 如何实现异步?

回答:「@Async + @EnableAsync。但要注意:1)@Async 方法必须在另一个 Bean 里(不能同类调用,因为是 AOP 代理);2)自定义线程池(默认的 SimpleAsyncTaskExecutor 每次都创建新线程);3)要有异常处理(实现 AsyncUncaughtExceptionHandler)。」

Q7:Spring Boot Starter 的原理?

回答:「Starter 就是一组依赖 + 自动配置。比如 spring-boot-starter-web 引入了 Spring MVC + 内嵌 Tomcat + Jackson,同时通过 AutoConfiguration.imports 注册 WebMvcAutoConfiguration。自定义 Starter 核心是写一个自动配置类,用条件注解控制生效时机。」

Q8:微服务之间如何传递用户信息?

回答:「网关鉴权后把 userId 放到请求头,通过 Feign/RestTemplate 的拦截器透传。也可以用 ThreadLocal 在单服务内传递。注意:跨线程(如 @Async、线程池)时要手动传递 ThreadLocal,或者用 InheritableThreadLocal。更好的方案是用 Micrometer 的 Context Propagation。」

Q9:如何做接口幂等?

回答:「看场景。创建类接口用唯一索引或 Token 机制;更新类接口用乐观锁(version 字段);支付回调用 Redis SETNX + 状态机。关键是幂等键的设计——不能只用请求参数,最好加上时间窗口。」

Q10:微服务如何做灰度发布?

回答:「Nacos 支持实例权重 + 元数据。网关根据请求头或用户 ID 路由到灰度实例。具体:灰度实例打 metadata.version=v2,网关配置路由规则,userId % 100 < 5 的用户路由到 v2 版本。配合链路追踪标记灰度流量,方便监控灰度效果。」

Q11:Spring Boot 3.x 和 2.x 最大的区别是什么?

回答:「四个:1)JDK 最低 17,推荐 21(支持虚拟线程);2)javax 换 jakarta,影响大量第三方库;3)Native Image 支持,启动从秒级到毫秒级;4)Observability 内置,不用自己集成 Sleuth/Brave 了。」

Q12:什么是 AOT 编译?有什么好处?

回答:「AOT(Ahead of Time)是在编译期而不是运行期处理 Bean。Spring Boot 3.x 在编译时生成 BeanDefinition,减少运行期反射和动态代理。好处:启动快、内存省、Native Image 友好。缺点:不支持运行时动态生成 Bean。」

Q13:微服务如何做分布式配置?

回答:「我们用 Nacos Config。配置分环境、分版本,支持动态刷新(@RefreshScope)。配置变更实时推送到各服务,不用重启。关键配置变更要走审批流,有回滚能力。」

Q14:微服务如何做限流?

回答:「两层限流:1)网关层——Spring Cloud Gateway + Redis 令牌桶,防整体流量过大;2)服务层——Sentinel,按接口粒度控制。Sentinel 支持 QPS 限流、线程数限流、慢调用比例熔断。大促前要做全链路压测,确定限流阈值。」

Q15:分布式事务了解哪些方案?

回答:「2PC、TCC、SAGA、本地消息表、RocketMQ 事务消息、Seata AT。实际选型看场景:金融核心用 TCC,高并发异步场景用消息队列,快速落地用 Seata AT。我们电商项目用的是 RocketMQ 事务消息 + 本地消息表组合。」

Q16:如何保证微服务的可用性?

回答:「多层保障:1)多实例 + 负载均衡;2)熔断降级(Sentinel);3)超时 + 重试(指数退避);4)限流保护;5)健康检查 + 自动重启(K8s liveness probe);6)异地多活(核心场景)。」

Q17:Spring Boot 内嵌 Tomcat 的优缺点?

回答:「优点:开箱即用,部署简单,和 Spring 深度集成。缺点:性能调优空间有限,不适合超高并发场景。高并发我们用 Undertow 替换 Tomcat(性能更好),或者直接在前面加 Nginx 做反向代理。Spring Boot 3.x 还支持虚拟线程,Tomcat 线程池可以大幅缩小。」

Q18:如何做微服务的日志追踪?

回答:「全链路 traceId:1)网关生成 traceId,放到请求头;2)MDC(Mapped Diagnostic Context)把 traceId 注入到日志上下文;3)日志格式统一包含 traceId、spanId;4)日志收集到 ELK,按 traceId 检索。Spring Boot 3.x 用 Micrometer Tracing,自动传递 traceId。」

Q19:微服务如何做服务降级?

回答:「分核心和非核心。核心链路降级返回缓存数据或默认值,非核心链路直接熔断不返回。Sentinel 做熔断降级,配置慢调用比例或异常比例阈值,触发后走 Fallback 逻辑。关键是 Fallback 不能返回 null,要有兜底数据。」

Q20:你怎么理解 Spring Boot 的"约定大于配置"?

回答:「核心思想是:80% 的场景用默认配置就够了,只有 20% 的特殊场景才需要改配置。比如:引入 web starter 就自动有 Tomcat + Spring MVC;引入 DataSource 就自动配置连接池;端口默认 8080,不需要指定。这是通过自动配置类 + 条件注解实现的——默认提供一套实现,用户自定义 Bean 覆盖默认。」


附录:速查口诀

自动装配口诀

Boot 启动扫 imports,条件注解做判断。
有类有 Bean 才生效,用户自定义优先看。

启动流程口诀

推断类型加载器,环境配置先就位。
创建容器跑初始化,监听注册不能少。
refresh 是核心,Runner 最后跑。

Bean 生命周期口诀

实例化,注属性,Aware 回调走一遭。
Before 后初始化,代理创建在 After。
使用完毕调销毁,@PreDestroy 记心头。

分布式事务选型口诀

金融核心选 TCC,高并发走 MQ 消息。
快速落地用 Seata,长事务 SAGA 来兜底。
能不用就不用,最终一致性是王道。

使用说明:本手册适合面试前快速复习,建议配合实际项目经验理解每个知识点。面试时不要背答案,要结合自己的项目讲。


本内容由 Coze AI 生成,请遵循相关法律法规及《人工智能生成合成内容标识办法》使用与传播。

技术面试笔记 / 03_SpringBoot微服务速查手册_2026 0 0 cosolar
2026-08-30T02:14:22.251365327Z 2026-08-30T02:17:12.734729805Z