02 - Spring框架与微服务 · 高频面试考题背诵指南


目录


一、Spring Core

Q1:Spring IOC 的工作原理?BeanFactory 和 ApplicationContext 的区别?

核心考点:控制反转思想、容器启动流程、两种容器的差异。

背诵话术

IOC(控制反转) 的核心思想是:对象的创建和依赖关系的管理不再由业务代码自己控制,而是交给 Spring 容器来负责。我们只需要通过注解或 XML 配置声明 Bean 的定义,容器会在启动时扫描这些定义,完成 Bean 的实例化、属性填充和依赖注入,并将 Bean 存储在内部的 Map<String, BeanDefinition> 结构中。

BeanFactory vs ApplicationContext

  • BeanFactory 是最基础的 IOC 容器接口,采用懒加载策略,只有在第一次调用 getBean() 时才实例化 Bean,功能较为简单。
  • ApplicationContext 继承自 BeanFactory,是更完整的企业级容器,支持饿加载(容器启动时就实例化所有单例 Bean)、国际化(i18n)、事件发布(ApplicationEvent)、AOP 自动代理等扩展功能。生产项目中一律使用 ApplicationContext

Q2:Spring Bean 的完整生命周期

核心考点:从实例化到销毁的完整 11 个步骤。

背诵话术

Spring Bean 的完整生命周期如下:

  1. 实例化(Instantiation):容器通过反射调用构造方法创建 Bean 的原始对象(此时属性还未填充)。
  2. 属性填充(Populate Properties):将配置文件或注解中声明的属性值和依赖的其他 Bean 注入进来(@Autowired@Value 在这一步生效)。
  3. Aware 接口回调:如果 Bean 实现了 BeanNameAwareBeanFactoryAwareApplicationContextAware 等接口,容器会依次回调对应的 setXxx() 方法,让 Bean 能感知到容器的相关信息。
  4. BeanPostProcessor 前置处理(postProcessBeforeInitialization:对 Bean 进行初始化前的增强处理,Spring AOP 的代理对象就是在 BeanPostProcessor 中创建的。
  5. 初始化(Initialization):依次执行 @PostConstruct 注解方法 → InitializingBean.afterPropertiesSet() → XML 中配置的 init-method
  6. BeanPostProcessor 后置处理(postProcessAfterInitialization:初始化后的增强,Spring AOP 代理实际上在此阶段生成并替换原始 Bean
  7. Bean 就绪,放入单例池(singletonObjects):Bean 可以被正常使用。
  8. 销毁(Destruction):容器关闭时,依次执行 @PreDestroyDisposableBean.destroy() → XML 配置的 destroy-method

Q3:Spring AOP 原理?JDK 动态代理和 CGLIB 代理的区别?

核心考点:代理模式,两种代理的底层实现,何时用哪种。

背诵话术

Spring AOP 的本质是动态代理。Spring 会在 Bean 初始化的 BeanPostProcessor 后置处理阶段,判断该 Bean 是否需要被 AOP 切面增强,如果需要,则为该 Bean 创建一个代理对象并返回,后续从容器中获取到的就是这个代理对象。

Spring 支持两种代理方式:

JDK 动态代理

  • 要求目标类必须实现至少一个接口
  • 代理对象通过 java.lang.reflect.Proxy.newProxyInstance() 创建,代理对象实现了与目标类相同的接口。
  • 方法调用通过 InvocationHandler.invoke() 进行拦截和增强。

CGLIB 代理

  • 不要求目标类实现接口,适用于没有接口的普通类。
  • 通过字节码技术(ASM)在运行时动态生成目标类的子类作为代理对象,通过重写父类方法来实现拦截。
  • 因为是继承方式实现,final 修饰的类和方法无法被代理

选择策略:在 Spring Boot 2.x 中,默认强制使用 CGLIB(spring.aop.proxy-target-class=true),因为 CGLIB 不需要依赖接口,更通用。


Q4:Spring 如何解决循环依赖?三级缓存各自的作用?

核心考点:三个 Map 的存储内容,解决循环依赖的完整流程,为何需要三级而不是二级。

背诵话术

Spring 通过三级缓存来解决单例 Bean 之间的循环依赖:

  • 一级缓存(singletonObjects:存储完全初始化好的 Bean,可以直接对外使用。
  • 二级缓存(earlySingletonObjects:存储提前暴露的、尚未完全初始化的 Bean 对象(已实例化但属性还未填充)。
  • 三级缓存(singletonFactories:存储 Bean 的工厂对象(ObjectFactory,调用工厂的 getObject() 方法可以得到 Bean 的早期引用(可能是代理对象)。

解决循环依赖的流程(A 依赖 B,B 依赖 A)

  1. 创建 A,A 实例化后,将 A 的 ObjectFactory 放入三级缓存
  2. A 开始填充属性,发现需要注入 B,触发 B 的创建。
  3. 创建 B,B 实例化后,将 B 的 ObjectFactory 放入三级缓存。
  4. B 填充属性时,发现需要注入 A,去三级缓存中找到 A 的工厂,调用 getObject() 获取 A 的早期引用,并将其升级到二级缓存,A 的工厂从三级缓存中移除。
  5. B 成功注入了 A 的早期引用,B 完成初始化,进入一级缓存
  6. A 继续完成属性填充(注入了完整的 B),A 完成初始化,进入一级缓存。

为什么需要三级而不是二级:三级缓存中存的是 ObjectFactory 而不是对象本身,目的是支持 AOP 代理。如果 A 需要被 AOP 代理,则调用 ObjectFactory.getObject() 时会返回 A 的代理对象而非原始对象,确保 B 注入的是 A 的代理版本。如果只有二级缓存(直接存原始对象),就无法在循环依赖场景下保证注入的是正确的代理对象。


Q5:@Autowired 和 @Resource 的区别?

核心考点:注入方式、来源规范、按类型 vs 按名称。

背诵话术

  • @Autowired:Spring 原生注解,优先按类型(byType)注入。如果容器中有多个相同类型的 Bean,则再按字段名(byName)进行匹配,也可以配合 @Qualifier 指定 Bean 名称。
  • @Resource:JDK 原生注解(javax.annotation),优先按名称(byName)注入。如果找不到匹配名称,再按类型匹配。适合希望减少对 Spring 框架依赖的场景。

实际开发中两者差别不大,@Autowired 更常用,但当接口有多个实现类时,@Autowired + @Qualifier("beanName")@Resource(name="beanName") 来明确指定是最清晰的做法。


Q6:@Transactional 失效的场景(至少 5 种)

核心考点:AOP 代理机制导致的各种失效场景。

背诵话术

@Transactional 失效最常见的场景有以下几种:

  1. 自我调用(同类内部调用):在同一个 Service 类中,方法 A(无事务)直接调用方法 B(有 @Transactional),因为 A 内部调用 B 是通过 this.B(),没有走 Spring 的代理对象,事务切面无法被触发,事务完全失效。解决方法:通过 ApplicationContext 获取自身代理对象再调用,或将 B 方法抽取到另一个 Service 类中。
  2. 方法非 public:Spring 事务的 AOP 拦截器只对 public 方法生效,privateprotected 或包级别方法上的 @Transactional 会被忽略。
  3. 异常被 catch 吞掉:方法内部用 try-catch 捕获了异常,没有在 catch 中重新抛出,Spring 的事务管理器感知不到异常,事务不会回滚。
  4. 异常类型不匹配@Transactional 默认只对 RuntimeExceptionError 回滚,如果抛出的是 IOException 等受检异常,事务不会回滚。需要配置 @Transactional(rollbackFor = Exception.class)
  5. 数据库不支持事务:如使用 MySQL 的 MyISAM 存储引擎,本身不支持事务,注解无效。
  6. Bean 未被 Spring 管理:如果类没有被 Spring 扫描到(忘加 @Service),不在容器中,自然没有代理。
  7. 多线程中失效@Transactional 的事务是绑定在当前线程的 Connection 上的,如果方法内开启了新线程去执行数据库操作,新线程拿到的是不同的 Connection,不在同一个事务中。

Q7:Spring 事务的 7 种传播行为

核心考点:各传播行为对当前事务的处理逻辑,REQUIRED vs REQUIRES_NEW vs NESTED 的区别。

背诵话术

Spring 事务传播行为定义了”当一个事务方法被另一个事务方法调用时,该如何处理事务”:

传播行为 说明
REQUIRED(默认) 有事务则加入,没有则新建。最常用。
REQUIRES_NEW 无论如何都新建一个独立事务,挂起当前事务。两个事务互不影响,互不回滚。
NESTED 在当前事务内创建一个嵌套事务(保存点 Savepoint),子事务可以独立回滚到保存点,不影响父事务;但父事务回滚会导致子事务也回滚。
SUPPORTS 有事务则加入,没有事务则以非事务方式执行。
NOT_SUPPORTED 以非事务方式执行,若当前有事务则挂起事务。
MANDATORY 必须在事务中执行,若没有活动事务则抛异常。
NEVER 以非事务方式执行,若当前有事务则抛异常。

实际项目中,REQUIRES_NEW 常用于”子操作失败不影响主流程”的场景,比如在招行调度中台中,记录操作日志的方法使用 REQUIRES_NEW,即使日志写入失败也不影响主业务事务的提交。


二、SpringBoot

Q8:SpringBoot 自动装配原理?@SpringBootApplication 做了什么?

核心考点:组合注解、@EnableAutoConfigurationspring.factories SPI 机制。

背诵话术

@SpringBootApplication 是一个组合注解,包含了三个核心注解:

  1. @SpringBootConfiguration:标识这是一个 Spring 配置类(本质是 @Configuration)。
  2. @ComponentScan:开启组件扫描,默认扫描主启动类所在包及其子包下的所有 @Component@Service@Repository@Controller 等注解。
  3. @EnableAutoConfiguration:这是自动装配的核心。

@EnableAutoConfiguration 的工作原理

  1. 它通过 @Import(AutoConfigurationImportSelector.class) 导入一个选择器。
  2. 这个选择器的 selectImports() 方法会扫描所有 JAR 包的 META-INF/spring.factories 文件(JDK SPI 扩展机制),读取 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键下所有的自动配置类全限定名(通常有 100+ 个)。
  3. 然后通过 @ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty 等条件注解进行过滤,只有当条件满足时(比如类路径下存在某个类),对应的自动配置类才会生效。
  4. 最终将满足条件的配置类注册到 Spring 容器中,完成相关 Bean 的自动创建。

💡 SpringBoot 3.x 版本变更
从 SpringBoot 3.0 开始,官方不再默认扫描 META-INF/spring.factories 文件。自动装配的配置文件路径改为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。每个自动配置类的类名单独占一行,不再需要以逗号分隔,面试时需特别注意项目所使用的版本。


Q9:MyBatis 的一级缓存和二级缓存?分别有什么坑?

核心考点:缓存作用域(SqlSession vs Mapper/Namespace),脏数据问题。

背诵话术

一级缓存(SqlSession 级别):默认开启,生命周期与 SqlSession 相同。同一个 SqlSession 内,相同的查询语句和参数第二次查询时直接从缓存中返回,不访问数据库。

:在分布式或多 SqlSession 场景下,如果 Session A 修改了数据,Session B 的一级缓存中还保存着旧数据,会读取到脏数据。另外,执行 insertupdatedelete 操作后,当前 SqlSession 的一级缓存会被清空。

二级缓存(Mapper/Namespace 级别):需要手动开启(在 mapper.xml 中加 <cache/>),生命周期与 SqlSessionFactory 相同,可以跨 SqlSession 共享。

坑(非常危险):多表联查时,如果查询涉及表 A 和表 B,但缓存的 namespace 只绑定了 Mapper A,当表 B 数据变更时,Mapper A 的缓存不会失效,会读到脏数据。因此,生产中一般禁用 MyBatis 的二级缓存,而是使用 Redis 等统一的分布式缓存方案来替代。


Q10:MyBatis 的 #{} 和 ${} 的区别?

核心考点:预编译占位符 vs 字符串替换,SQL 注入风险。

背诵话术

  • #{}(预编译占位符):MyBatis 会将 #{} 替换为 ?,通过 JDBC 的 PreparedStatement 预编译处理,传入的参数值会作为字符串被转义,完全防止 SQL 注入。这是绝大多数场景下的首选。
  • ${}(字符串拼接):直接将参数值替换到 SQL 语句中,不做任何转义,存在严重的 SQL 注入风险。例如:SELECT * FROM user WHERE name = '${name}',如果 name 传入 ' OR 1=1 --,就会执行 SELECT * FROM user WHERE name = '' OR 1=1 --,查出所有用户数据。

${} 唯一合理的使用场景是动态传入表名或列名(因为这类内容无法通过 ? 参数传递),但此时必须在代码层面对传入值进行严格的白名单校验,杜绝用户直接控制输入。


三、Spring Cloud 微服务

Q11:Nacos 注册中心工作原理?和 Eureka 的区别?

核心考点:服务注册/发现机制,AP vs CP,Nacos 推送 vs Eureka 拉取。

背诵话术

Nacos 工作原理:服务启动时,将自身的 IP、端口、服务名等信息向 Nacos Server 进行注册,Nacos 维护一个服务注册表。客户端(调用方)向 Nacos 发起订阅,Nacos 会主动将服务实例列表推送给订阅方,同时客户端也会定期从 Nacos 拉取最新列表作为兜底(推拉结合)。Nacos 通过心跳机制(默认 5s 一次)检测服务健康状态,如果 15s 内未收到心跳,将该实例标记为不健康,30s 后从注册表中剔除。

与 Eureka 的主要区别

特性 Nacos Eureka
一致性模型 支持 AP(默认)和 CP(可切换) 只支持 AP
通知机制 主动推送 客户端定时拉取(30s/次,更新慢)
健康检测 支持 TCP/HTTP/MySQL 等多种健康检查 仅 HTTP 心跳
配置中心 内置 需配合 Spring Cloud Config
维护状态 阿里开源,活跃维护 Netflix 官方停止维护

在我们 SRM 和招行项目中均使用 Nacos 作为注册和配置中心,主要看中的是其推送机制带来的更快的服务发现响应,以及内置的配置中心能力。


Q12:Sentinel 的限流算法和熔断策略

核心考点:滑动窗口限流,三种熔断策略(慢调用/异常比例/异常数)。

背诵话术

Sentinel 的限流算法

  • 滑动窗口算法(默认):将 1 秒划分为多个小窗口(默认 10 个,每个 100ms),统计每个小窗口内的请求量,滑动求和判断是否超阈值。比固定窗口算法更平滑,不会出现边界突刺问题。
  • 漏桶算法(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER:请求以固定速率匀速通过,超出速率的请求排队等待(队列模式),适合流量整形场景。
  • 令牌桶算法:令牌以固定速率生成,请求消耗令牌,令牌满了停止生成,支持一定程度的流量突发。

Sentinel 的三种熔断策略

  1. 慢调用比例:统计窗口期内,响应时间超过阈值(如 500ms)的请求占比超过设定比例(如 50%),触发熔断。熔断后进入半开状态,允许少量探测请求通过。
  2. 异常比例:统计窗口期内,异常请求占总请求的比例超过阈值,触发熔断。
  3. 异常数:统计窗口期内,异常请求的绝对数量超过阈值,触发熔断。

在招行调度中台中,我们对所有 Feign 外部 RPC 调用配置了慢调用比例熔断,设定响应超过 2s 且慢调用比例超过 30% 时熔断 30s,降级返回兜底数据,防止因下游服务”假死”拖垮上游。


Q13:Seata 的 TCC 模式原理?AT 模式和 TCC 的区别?

核心考点:两阶段提交,AT 模式的自动回滚(undo_log),TCC 的业务侵入性。

背诵话术

AT 模式(自动):对业务代码无侵入,由 Seata 自动拦截 SQL,在执行前后生成 undo_log(回滚日志)。第一阶段:直接提交本地事务,释放数据库锁,并将 undo_log 持久化。第二阶段:如果全局事务提交成功,删除 undo_log;如果全局事务回滚,通过 undo_log 自动反向补偿恢复数据。AT 模式使用了全局行锁,高并发下性能有一定损耗。

TCC 模式(手动):将业务逻辑拆分为三个方法:

  • Try:预留资源(如冻结库存、预扣余额),检查业务可行性。
  • Confirm:确认执行,消耗 Try 阶段预留的资源(真正扣减)。全局事务提交时调用。
  • Cancel:取消执行,释放 Try 阶段预留的资源(解冻)。全局事务回滚时调用。

核心区别:AT 模式对代码无侵入但有全局锁,适合并发量一般的场景;TCC 模式需要开发者手动实现三个方法,有业务侵入性,但不依赖数据库全局锁,并发性能更高,适合金融级高并发场景。在招行核心调度中台里,关键的资金流转操作使用了 TCC 模式保证分布式事务的强一致性。


Q14:TCC 模式的三大异常场景(空回滚、悬挂、幂等)

核心考点:TCC 的三个难题,各自解决手段。

背诵话术

TCC 的核心难点不在于写 Try/Confirm/Cancel,而在于处理异常场景:

1. 空回滚(Empty Rollback)

  • 场景:Try 阶段由于网络超时,被判定为失败,TC(事务协调器)发起 Cancel。但 Try 请求其实根本没到达过调用方(或到达了但调用方没执行),Cancel 被执行时本地根本没有对应的预留资源。
  • 解决:Cancel 操作需要支持空回滚——如果没找到对应的 Try 记录,Cancel 不能抛异常,而是记录一条”已回滚”标记,然后返回成功。

2. 悬挂(Suspend)

  • 场景:Cancel 比 Try 先到达。TC 先发起 Cancel(如 Try 超时),Cancel 执行完了,然后之前”堵在半路上的”Try 请求后到达执行了。如果 Try 执行成功并预扣了资源,这笔资源就永久被锁死了(Cancel 已经执行完了,没人来解冻)。
  • 解决:Cancel 执行时记录一条”已回滚”标记。Try 执行前先检查该标记,如果发现”已回滚”,则拒绝执行 Try(返回失败),阻止悬挂的发生

3. 幂等控制:Try / Confirm / Cancel 三个操作都可能因网络重试被多次调用,所以三者都必须是幂等的——重复执行结果一致。通常用业务唯一 ID 做唯一索引防重。

Seata TCC 框架的处理:Seata 的 TCC 模式通过维护一张事务记录表自动处理了空回滚和悬挂——Try 前查是否有 Cancel 记录(防悬挂),Cancel 前查是否有 Try 记录(空回滚则记录标记),Confirm/Cancel 成功后记录状态(防幂等)。


Q15:可靠消息最终一致性(本地消息表方案)

核心考点:本地事务 + 本地消息表 + 定时任务重试,适合高可用场景。

背诵话术

可靠消息最终一致性是分布式事务中最常用的柔性方案,不需要两阶段提交,适合对实时一致性要求不高、但对可用性要求高的业务场景。

本地消息表方案(RocketMQ 事务消息同理)

  1. 业务方(生产者):在自己的数据库中,将业务操作消息记录放在同一个本地事务中完成(如”创建订单” + “写入一条 MQ 消息记录”)。本地事务保证要么都成功要么都失败。
  2. 消息发送:定时任务轮询本地消息表中状态为”未发送”的记录,将消息投递到 MQ。发送成功后将记录状态更新为”已发送”。
  3. 消费方:消费消息,正常处理业务逻辑。消费完成后提交 offset。如果消费失败,MQ 重投或死信队列兜底。消费者必须有幂等性防止重复消费。
  4. 补偿检查:定时任务扫描超时未确认的消息(已发送但未消费或消费失败),进行人工处理或补偿。

在招行调度中台的应用:流程调度中的回调通知场景使用了可靠消息方案(不是金融转账核心场景,那个才用 TCC)。流程执行完成后,在本地事务中同时写入回调消息记录,后台定时任务投递到 Kafka,下游系统幂等消费。这套方案保证了即使回调系统暂时不可用(网络闪断),消息也不会丢失,最大程度保证了流程状态的最终一致性。


Q16:2PC / 3PC / TCC / Saga / 可靠消息 五大方案对比

核心考点:各方案的一致性、性能、业务侵入性的权衡。

背诵话术

方案 一致性 性能 业务侵入 适用场景
2PC(XA) 强一致 差(全程锁资源) 低(数据库直接支持) 传统单体应用、并发低场景
3PC 强一致(比 2PC 略好) 基本不用(2PC 的改良版,引入超时机制防阻塞),成本高,生态差
TCC 最终强一致 好(不长期锁资源) 高(需实现 Try/Confirm/Cancel) 金融核心交易、库存扣减
Saga 最终一致 好(无锁) 中(需实现正向+补偿) 长流程业务、微服务编排
可靠消息最终一致 最终一致(可能有短暂窗口) 最好(完全异步) 低(只需发消息+幂等消费) 通知类、回调类、解耦场景

选型要点:核心金融资金用 TCC(强一致 + 高性能),通知回调用可靠消息(高吞吐、低耦合),跨多微服务的复杂长流程可以考虑 Saga(每个参与者独立提交 + 补偿回滚),2PC 基本不用于分布式场景(锁资源太久,性能太差)。

在招行项目中,资金流转使用 TCC 模式(如节点流程执行中的状态扣减、冻结),回调通知下游使用可靠消息最终一致性方案(异步通知 + Kafka 投递 + 幂等消费)。


Q17:Feign 的超时、重试与负载均衡原理?

核心考点:声明式客户端、Feign 的调用执行流程、超时配置冲突、Ribbon / LoadBalancer 负载均衡原理。

背诵话术

Feign 工作原理
Feign 是一个声明式的 HTTP 客户端。通过在接口上添加 @FeignClient 注解,Spring 容器启动时,会为该接口生成 JDK 动态代理对象(对应的 Handler 为 FeignInvocationHandler)。当调用接口方法时,代理对象拦截请求,通过 SynchronousMethodHandlerexecuteAndDecode() 方法进行处理:将方法参数通过 Encoder 序列化为 HTTP 请求体,生成一个 Request 对象,接着经过负载均衡器选择实例,交由底层的 Client(如 OkHttp/HttpClient/HttpURLConnection)发送 HTTP 请求,最后通过 Decoder 反序列化为接口返回值。

超时与重试
Feign 内部默认有重试机制(默认不启用或重试 5 次,但微服务组件一般关闭它),超时默认是 10s(Read)和 20s(Connect)。
在招行分布式环境的超时干预中
我们一般关闭 Feign 的默认重试,并将超时控制权交给 Ribbon(或 Spring Cloud LoadBalancer),通过如下配置进行精细干预:

1
2
3
4
5
ribbon:
ReadTimeout: 2000 # 业务处理超时时间 2s
ConnectTimeout: 1000 # 连接超时时间 1s
MaxAutoRetries: 0 # 同一实例重试次数,设为 0
MaxAutoRetriesNextServer: 1 # 切换实例重试次数,设为 1

对于写操作等非幂等接口,需关闭重试,以防止网络抖动导致的重复提交。

负载均衡机制
Feign 会集成 Ribbon(或 Spring Cloud LoadBalancer)。Ribbon 从注册中心(如 Nacos)获取服务实例列表,本地维护一个缓存,并在发起请求时通过负载均衡算法(如 RoundRobinRule 轮询、RandomRule 随机、BestAvailableRule 最小并发数)计算出一个健康的实例 IP 和端口,最后拦截 Feign 的 Request 并重写 URL 进行请求。


Q18:Spring Cloud Gateway 核心架构与应用?

核心考点:Gateway vs Zuul 1.x、网关三大核心概念(Route, Predicate, Filter)、自定义拦截器鉴权与限流。

背诵话术

Gateway vs Zuul 1.x

  • Zuul 1.x 基于 Servlet 2.5 构建,是同步阻塞 I/O 架构。每个请求占用一个线程,在高并发场景下极易耗尽线程池。
  • Spring Cloud Gateway 基于 Spring WebFlux 和 Netty 构建,是异步非阻塞(Reactive)架构,使用极少量的线程就能处理大量并发请求,吞吐量和并发性能大幅领先。

核心概念

  1. Route(路由):网关的基本模块,由 ID、目标 URI、断言集合、过滤器集合组成。
  2. Predicate(断言):Java 8 的 Predicate 接口,用于匹配请求属性(如 Path 路径、Method 方法、Header 请求头等)。
  3. Filter(过滤器):GatewayFilter 实例,在发送请求到下游服务之前(pre)或之后(post)修改请求/响应。

自定义 Filter 拦截器实战
在我们医博系统和 OpenAPI 开放平台中,我们自定义了 GlobalFilterGatewayFilterFactory 实现如下功能:

  • 统一鉴权:在 pre 阶段,从请求头获取 JWT Token,进行合法性校验、解析并将解析出的 userId/role 信息写入 ServerHttpRequest 的 Header 中传递给下游微服务。若无效,直接将 Http 状态码设为 401 并结束请求。
  • 分布式限流:使用 Gateway 的 RequestRateLimiter 过滤器,结合 Redis 和 Lua 脚本实现令牌桶限流算法。针对不同 API 或不同租户设定不同的 Rate 和 Capacity。
  • 灰度发布/路由干预:根据请求头中的特定版本号(如 x-version: v2)动态修改 ServerWebExchange 的路由目标,实现金丝雀/灰度流量分流。