Skip to content

本轮 SpringCloud微服务架构面试题库(带答案) ​

生成时间:2026-05-21 21:24


【面试题】1. Eureka的自我保护机制是什么?什么场景下会触发?生产环境要不要关闭? ​

【标准答案】Eureka的自我保护机制是一种容错设计,核心思想是:宁可保留错误的服务注册信息,也不要盲目注销任何健康服务。

触发条件:当Eureka Server在短时间内丢失超过85%的心跳(默认阈值),会认为网络分区故障发生了,此时进入自我保护模式,不再剔除任何服务实例。

为什么需要它:如果Eureka Server和微服务之间网络抖动,但服务本身是健康的,没有自我保护的话,服务会被错误剔除,导致服务不可用。有了自我保护,即使心跳丢失,服务注册信息仍会保留,等网络恢复后服务继续可用。

生产环境建议:不建议关闭。虽然自我保护会导致下线服务仍显示在注册表中,但相比错误剔除健康服务,这个代价是可接受的。可以通过调整阈值(eureka.server.renewal-percent-threshold)来优化触发灵敏度。


【面试题】2. Ribbon有哪些负载均衡策略?实际项目中怎么选择? ​

【标准答案】Ribbon提供7种核心策略:

常用策略:

  • 轮询(RoundRobin):默认策略,按顺序依次调用,适合服务器性能相近的场景
  • 随机(Random):随机选择,简单但分布不够均匀
  • 加权轮询(WeightedResponseTime):根据响应时间动态分配权重,响应快的节点获得更多请求,适合服务器性能不均的场景
  • 最少并发(BestAvailable):选择并发请求最少的实例,适合长连接场景
  • 重试(Retry):在轮询基础上增加重试,适合对可用性要求高的场景

实际选型建议:

  • 服务器性能相近:轮询即可
  • 服务器配置差异大:加权轮询
  • 接口响应时间差异明显:WeightedResponseTime自动调节
  • 需要高可用:轮询+重试组合

自定义策略:实现IRule接口,在choose方法中编写自己的负载均衡逻辑,比如根据请求参数路由到特定服务实例(灰度发布场景)。


【面试题】3. OpenFeign的超时重试配置怎么做?有哪些坑需要注意? ​

【标准答案】超时配置:

yaml
ribbon:
  ReadTimeout: 5000    # 读取超时
  ConnectTimeout: 1000 # 连接超时
  
feign:
  client:
    config:
      default:
        connectTimeout: 1000
        readTimeout: 5000

重试机制:

  • Ribbon默认重试:同一实例最大重试1次,切换实例最大重试1次(MaxAutoRetries=1, MaxAutoRetriesNextServer=1)
  • 禁用重试:MaxAutoRetries=0, MaxAutoRetriesNextServer=0

常见坑点:

  1. 双重超时问题:如果用了Hystrix,Hystrix的超时要大于Ribbon超时+重试次数,否则Ribbon还在重试,Hystrix已经熔断了
  2. 幂等性问题:重试只适合GET请求,POST请求重试可能导致重复提交,需要业务层做幂等处理
  3. 重试风暴:如果下游服务响应慢,大量请求重试会放大压力,需要合理配置重试次数
  4. 配置不生效:Ribbon配置要放在application.yml,而不是bootstrap.yml,且必须在服务启动前加载

【面试题】4. Sentinel的限流算法有哪些?各自适用场景是什么? ​

【标准答案】Sentinel支持三种核心限流算法:

1. QPS限流(直接拒绝):

  • 超过阈值直接拒绝,返回Blocked异常
  • 适合API网关、秒杀场景,快速失败,保护系统不被压垮

2. 冷启动限流(Warm Up):

  • 系统启动时缓慢增加流量,避免瞬间高并发压垮冷系统
  • 阈值从阈值/3(默认)逐步提升到最大阈值
  • 适合秒杀系统刚启动、缓存预热场景

3. 恒定等待限流(排队等待):

  • 请求在队列中排队,匀速通过
  • 适合削峰填谷,比如消息处理、定时任务
  • 设置超时时间,超时后拒绝

限流模式选择:

  • 直接拒绝:追求快速响应,允许部分失败
  • Warm Up:保护冷系统,平滑启动
  • 排队等待:请求必须全部处理,可以接受延迟

关联限流:当关联资源达到阈值时,限流当前资源。比如:查询接口和写入接口关联,写入繁忙时限流查询,保护数据库。


【面试题】5. Spring Cloud Gateway的过滤器链执行顺序是怎样的?如何自定义全局过滤器? ​

【标准答案】过滤器分类:

  • 前置过滤器(Pre):请求转发前执行,如参数校验、鉴权、限流
  • 后置过滤器(Post):响应返回后执行,如添加响应头、日志记录、跨域处理
  • 全局过滤器(GlobalFilter):对所有路由生效

执行顺序:

  • 过滤器通过order值排序,值越小优先级越高
  • Pre过滤器按order升序执行
  • Post过滤器按order降序执行(与Pre相反)

自定义全局过滤器示例:

java
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 验证token逻辑
        return chain.filter(exchange); // 放行
    }
    
    @Override
    public int getOrder() {
        return 0; // order值越小越先执行
    }
}

关键点:

  • GlobalFilter + Ordered接口实现
  • chain.filter(exchange)表示放行,继续执行下一个过滤器
  • return之前可以添加Post逻辑(通过Mono的then方法)
  • 优先级高的过滤器要放在前面,比如鉴权在限流之前

【面试题】6. Nacos配置中心如何实现配置热更新?应用端需要做什么? ​

【标准答案】热更新原理:

Nacos配置热更新基于长轮询机制:

  1. 客户端向Nacos Server发起长轮询请求(默认30秒超时)
  2. 如果配置有变化,Server立即返回最新配置
  3. 如果无变化,请求挂起,直到超时或配置变更
  4. 客户端收到响应后,更新本地缓存,触发配置变更事件

应用端实现方式:

方式一:@RefreshScope注解

java
@RestController
@RefreshScope
public class ConfigController {
    @Value("${app.config}")
    private String config;
    
    @GetMapping("/config")
    public String getConfig() {
        return config;
    }
}
  • 加上@RefreshScope后,配置变更时Bean会重新创建,属性自动更新
  • 注意:只支持@Value注解,不支持@ConfigurationProperties的类

方式二:配置监听器

java
@Component
public class ConfigListener implements ApplicationListener<NacosConfigReceivedEvent> {
    @Override
    public void onApplicationEvent(NacosConfigReceivedEvent event) {
        // 配置变更时执行逻辑
        String newConfig = event.getContent();
    }
}

注意事项:

  • @RefreshScope有性能开销,Bean会被代理,按需使用
  • 配置变更粒度:dataId维度,不支持单个属性监听
  • 多环境配置:通过namespace和group隔离
  • 灰度发布:结合元数据实现按比例推送

【面试题】7. Sleuth链路追踪如何生成和传递TraceId?采样策略怎么配置? ​

【标准答案】TraceId生成:

  • Sleuth默认使用64位随机数生成TraceId
  • 格式:16进制字符串,如:5e5a8c3d9f2e1b0a
  • 整个调用链路唯一,贯穿所有服务

SpanId生成:

  • 每个服务实例生成自己的SpanId
  • 格式同TraceId,作用域为单个服务

传递机制:

  • HTTP调用:通过HTTP Header传递(X-B3-TraceId、X-B3-SpanId)
  • 异步消息:通过消息Header传递(MQ消息头)
  • 框架自动完成传递,业务代码无感知

采样策略配置:

yaml
spring:
  sleuth:
    sampler:
      probability: 0.1  # 采样率10%

采样策略选择:

  • 全采样(probability=1.0):适合测试环境,问题定位精准
  • 低采样(probability=0.01~0.1):生产环境推荐,减少存储和性能开销
  • 自定义采样:实现Sampler接口,根据业务逻辑决定是否采样

性能影响:

  • 采样率100%:每个请求生成Trace/Span,有一定性能开销(内存、网络、存储)
  • 采样率过低:可能遗漏问题请求,排查困难
  • 建议:生产环境0.1~0.3,核心链路可以调高

【面试题】8. Seata的AT模式原理是什么?为什么推荐使用? ​

【标准答案】AT模式原理:

AT模式是Seata推荐的非侵入式分布式事务方案,核心机制:

一阶段:

  • 执行业务SQL,记录数据快照(before image)
  • 提交本地事务,释放锁
  • 记录after image,生成回滚日志(undo log)
  • 向TC(事务协调者)注册分支事务

二阶段:

  • 全局提交:异步删除undo log,立即返回(性能高)
  • 全局回滚:根据undo log反向生成SQL恢复数据

为什么推荐AT模式:

  1. 无侵入:业务代码无需修改,只需加注解@GlobalTransactional
  2. 性能好:一阶段本地提交,二阶段异步提交,锁持有时间短
  3. 简单易用:相比TCC不需要写三个接口(try/confirm/cancel)
  4. 支持主流数据库:MySQL、PostgreSQL、Oracle等

AT模式限制:

  • 不支持多表关联的SQL(join)
  • 需要主键
  • 写隔离:需要全局锁,可能死锁
  • 读隔离:默认读未提交,脏读风险(可配置读已提交)

适用场景:大多数业务系统,对一致性要求不是极端严格的场景。


【面试题】9. Redisson分布式锁的看门狗机制是什么?怎么防止锁过期? ​

【标准答案】看门狗机制:

Redisson分布式锁默认有过期时间(默认30秒),如果业务执行时间超过30秒,锁会自动释放,导致并发问题。看门狗机制就是为了解决这个问题。

工作原理:

  1. 加锁成功后,Redisson启动一个定时任务(看门狗)
  2. 每隔过期时间的1/3(默认10秒)检查一次锁
  3. 如果线程仍持有锁,自动续期(重置过期时间为30秒)
  4. 业务执行完毕,主动释放锁,看门狗停止

核心源码:

java
// 加锁时启用看门狗
RLock lock = redisson.getLock("myLock");
lock.lock();  // 默认启用看门狗,过期时间30秒

手动设置过期时间:

java
lock.lock(10, TimeUnit.SECONDS);  // 手动设置10秒过期
// 注意:手动设置过期时间会禁用看门狗

防止锁过期的最佳实践:

  • 业务执行时间不确定:使用默认lock(),让看门狗自动续期
  • 业务执行时间确定且较短:手动设置过期时间,禁用看门狗减少开销
  • 业务执行时间可能很长:看门狗+业务层超时控制,避免无限续期

常见坑:

  • 忘记释放锁:使用try-finally确保unlock
  • 看门狗失效:手动设置过期时间会禁用看门狗
  • 锁重入:同一个线程多次加锁需要多次释放

【面试题】10. Spring Cloud Stream如何处理消息积压?有哪些优化策略? ​

【标准答案】消息积压原因:

  • 消费速度低于生产速度
  • 消费者处理逻辑慢(如数据库慢查询)
  • 消费者实例数不足
  • 消息堆积在Broker端

处理策略:

1. 增加消费者实例数

  • 水平扩容:增加Pod数量
  • 注意:实例数不能超过分区数(Kafka partition),否则多出的实例空闲

2. 提升单实例并发数

yaml
spring:
  cloud:
    stream:
      bindings:
        input:
          consumer:
            concurrency: 3  # 单实例开3个线程消费

3. 异步处理+批量入库

  • 消息异步处理,不阻塞主线程
  • 批量插入数据库,减少IO次数
  • 使用线程池控制并发

4. 降级策略

  • 积压严重时,跳过非核心逻辑(如日志记录、统计)
  • 持久化消息,延迟处理

5. 分区策略

  • 根据业务key分区,保证同一key的消息有序
  • 不同分区并行消费,提升吞吐

6. 监控告警

  • 监控消费延迟(lag)
  • 设置阈值告警,及时发现积压

最佳实践:

  • 生产者:控制发送速率,不要超过消费者处理能力
  • 消费者:处理逻辑要快,避免阻塞操作
  • 架构:削峰填谷,合理设置队列容量和消费者数量
  • 兜底:积压严重时,临时增加消费者实例,扩容后自动恢复

生成信息

  • 生成时间:2026-05-21 21:24
  • 题目数量:10道
  • 知识点覆盖:服务注册与发现、负载均衡、服务调用、熔断限流、API网关、配置中心、链路追踪、分布式事务、分布式锁、消息队列