Skip to content

SpringCloud微服务架构面试题库 ​

生成时间: 2026-05-21 23:01 题目数量: 10道


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

【面试题】1. Eureka和Nacos在服务注册发现机制上有何本质区别?生产环境如何选型? ​

【标准答案】 核心区别有三点:

1. 一致性模型不同

  • Eureka是AP模型,优先保证可用性,允许短暂的数据不一致
  • Nacos默认AP模式,可切换为CP模式(通过配置nacos.core.protocol.raft.data),在需要强一致的场景下更可靠

2. 功能定位不同

  • Eureka只做服务注册发现,配置中心需要Spring Cloud Config配合
  • Nacos集注册中心+配置中心于一体,开箱即用,运维成本低

3. 健康检查机制不同

  • Eureka依赖心跳续约,客户端30秒发一次心跳,服务端90秒没收到就剔除,还有自我保护机制防止误剔除
  • Nacos支持心跳模式(临时实例)和健康检查模式(持久化实例),更灵活

生产选型建议:

  • 已有Spring Cloud Netflix全家桶体系、团队熟悉Eureka → 继续用Eureka
  • 新项目、追求一体化解决方案、需要配置热更新 → 选Nacos
  • 强一致性要求高(金融支付场景)→ Nacos CP模式或Consul

【面试题】2. 熔断器的三种状态分别是什么?状态转换的触发条件是什么? ​

【标准答案】 熔断器采用状态机模式,三种状态:关闭(Closed)、打开(Open)、半开(Half-Open)

状态转换逻辑:

关闭状态(Closed):正常状态,请求直接通过

  • 触发打开条件:失败率达到阈值(如50%)或失败次数超限(如10次/10秒)
  • Hystrix默认:10秒内20次请求,失败率>50%触发熔断

打开状态(Open):熔断状态,请求直接拒绝,走降级逻辑

  • 持续时间:熔断器保持打开一段时间(如5秒),这期间所有请求快速失败
  • 触发半开条件:经过休眠时间后,自动进入半开状态

半开状态(Half-Open):探测状态,放行部分请求探测服务是否恢复

  • 恢复关闭条件:探测请求成功,认为服务恢复,切换回关闭状态
  • 恢复打开条件:探测请求失败,认为服务仍异常,重新进入打开状态,并重置休眠计时器

生产实践要点:

  • 休眠时间不宜太短,防止服务未恢复时频繁探测
  • 半开状态的探测请求量要控制,避免瞬间压垮恢复中的服务
  • Sentinel的熔断状态机类似,但支持更多策略(慢调用比例、异常比例、异常数)

【面试题】3. Sentinel的限流算法有哪些?令牌桶和漏桶算法的区别是什么? ​

【标准答案】 Sentinel支持多种限流算法:

1. 直接拒绝模式(QPS限流)

  • 超过阈值直接拒绝,抛出BlockException
  • 适合突发流量场景

2. 冷启动模式(Warm Up)

  • 系统启动时流量从阈值的一半逐步提升到最大值
  • 保护冷启动系统不被瞬间压垮
  • 避免缓存未预热时数据库被打满

3. 匀速排队模式

  • 请求在队列中排队,按固定间隔处理
  • 适合削峰填谷,保证请求有序处理

令牌桶 vs 漏桶核心区别:

令牌桶算法:

  • 以固定速率往桶里放令牌,请求到达时拿令牌,拿到才能通过
  • 特点:允许突发流量,桶里有令牌就能处理
  • 场景:需要处理突发请求,如秒杀场景

漏桶算法:

  • 请求像水一样流入桶,以固定速率从底部流出处理
  • 特点:强制平滑流量,不管请求多急,都按固定速率处理
  • 场景:保护下游系统,如数据库写入

生产配置示例(Sentinel):

java
FlowRule rule = new FlowRule();
rule.setResource("getResource");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100); // QPS阈值100
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setWarmUpPeriodSec(10); // 预热10秒

【面试题】4. Spring Cloud Gateway如何实现灰度发布?具体路由策略有哪些? ​

【标准答案】 Spring Cloud Gateway灰度发布核心是基于路由断言和过滤器实现流量分流。

实现方案:

1. 基于请求头的灰度

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: service-v1
          uri: lb://USER-SERVICE-V1
          predicates:
            - Path=/api/user/**
            - Header=version, v1
        - id: service-v2
          uri: lb://USER-SERVICE-V2
          predicates:
            - Path=/api/user/**
            - Header=version, v2

2. 基于权重的灰度

yaml
predicates:
  - Weight=user-service, 80  # 80%流量走v1版本

3. 基于URL参数的灰度

yaml
predicates:
  - Query=version, v2

4. 基于Cookie的灰度

yaml
predicates:
  - Cookie=version, v2

生产实践要点:

  • 灰度策略组合:先用Cookie/Header做内部测试,确认无问题后逐步放权重
  • 监控告警:灰度版本必须有独立的监控指标,实时观察错误率、响应时间
  • 快速回滚:发现问题立即调整权重为0,所有流量切回稳定版本
  • 全链路透传:灰度标识需要通过请求头在整个调用链透传(用Feign拦截器或Gateway过滤器)

完整灰度流程:

  1. 内部测试人员通过Header访问v2版本
  2. 验证通过后,开放5%流量给外部用户
  3. 观察监控指标,逐步提升到20%、50%、100%
  4. 全量后,下线v1版本

【面试题】5. Seata的AT模式和TCC模式有什么区别?各适用什么场景? ​

【标准答案】 Seata四种事务模式,最常用的是AT和TCC:

AT模式(Automatic Transaction):

特点:

  • 无侵入:业务代码不需要写事务补偿逻辑
  • 原理:通过解析SQL生成前后镜像,自动记录回滚日志
  • 两阶段提交:一阶段执行SQL并记录undo log,二阶段异步提交或回滚

优点:开发成本低,对业务代码零侵入 缺点:性能不如TCC,存在全局锁,有脏读风险

适用场景:

  • 大多数OLTP业务
  • 对并发性能要求不极端的场景
  • 团队希望快速落地分布式事务

TCC模式(Try-Confirm-Cancel):

特点:

  • 强侵入:业务代码必须实现Try、Confirm、Cancel三个接口
  • 原理:Try预留资源,Confirm确认提交,Cancel回滚补偿
  • 业务控制:事务逻辑由业务方完全控制

优点:性能高,无全局锁,一致性更强 缺点:开发成本高,要考虑各种异常场景

适用场景:

  • 高并发场景(如秒杀、抢红包)
  • 对一致性要求极高的金融场景
  • 业务逻辑复杂,需要精细控制回滚的场景

选型建议:

  • 90%场景用AT模式,开发效率高
  • 核心交易、支付等场景用TCC
  • 跨公司系统集成用Saga模式(长事务)
  • 对XA数据库用XA模式(性能最差)

【面试题】6. Redis分布式锁的SET NX EX命令如何保证原子性?Redisson做了哪些增强? ​

【标准答案】 SET NX EX原子性保证:

Redis的SET key value NX EX seconds命令是原子操作:

  • NX:只有key不存在时才设置(Not eXists)
  • EX:设置过期时间(秒)
  • 整个命令在Redis服务端一次性执行,不会被其他命令打断

为什么原子性重要:

bash
# 错误写法(非原子)
SETNX lock 1      # 成功
EXPIRE lock 10    # 如果这里宕机,锁永不过期,死锁!

Redisson增强特性:

1. 锁续期(Watch Dog)

  • 问题:业务执行时间超过锁过期时间,锁被自动释放
  • 解决:Redisson后台线程每10秒检查,业务还在执行就续期30秒
  • 代码:默认开启,无需手动配置

2. 可重入锁

  • 同一线程可多次获取同一把锁,内部维护计数器
  • 释放时计数器减1,到0才真正释放

3. 红锁(RedLock)

  • 问题:主从切换时锁可能丢失
  • 解决:同时向多个独立Redis节点申请锁,超过半数成功才算加锁成功
  • 场景:对锁可靠性要求极高的场景

4. 公平锁、读写锁、信号量

  • 公平锁:按请求顺序获取锁
  • 读写锁:读读共享、写写互斥、读写互斥

生产注意事项:

  • 锁的key要设置业务前缀,避免不同业务锁冲突
  • 锁value用UUID,释放时校验,防止误删别人的锁
  • 主从架构用RedLock,单机用普通锁即可

【面试题】7. Nacos配置中心如何实现配置热更新?ConfigListener的原理是什么? ​

【标准答案】 配置热更新实现原理:

1. 客户端长轮询机制

  • Nacos客户端启动时,向服务端发起长轮询请求(默认30秒超时)
  • 服务端配置没变化时,请求挂起直到超时或配置变更
  • 配置变更时,服务端立即返回变更通知

2. 配置变更流程:

Nacos控制台修改配置 → 服务端写入数据库 → 
唤醒所有监听该配置的长轮询请求 → 客户端收到通知 → 
拉取最新配置 → 触发ConfigListener回调 → 刷新本地缓存

ConfigListener原理:

使用方式:

java
@NacosConfigListener(dataId = "application.yml", groupId = "DEFAULT_GROUP")
public void onConfigChange(String newConfig) {
    log.info("配置变更:{}", newConfig);
    // 刷新本地Bean属性
    refreshBean();
}

原理分析:

  • 客户端维护一个CacheData对象,存储配置的本地缓存
  • 长轮询收到变更通知后,对比本地缓存的MD5
  • MD5变化时,触发所有注册的Listener回调

@RefreshScope注解原理:

  • Spring Cloud扩展了@Scope,标记@RefreshScope的Bean会被代理
  • 配置变更后,发送RefreshEvent事件
  • 代理Bean被销毁重建,重新从配置中心读取值

生产最佳实践:

  • 配置变更先在测试环境验证
  • 敏感配置用Nacos的配置加密功能(Jasypt)
  • 配置回滚要保留历史版本(Nacos支持30天历史)

【面试题】8. Spring Cloud Gateway如何实现统一鉴权?Token如何在服务间传递? ​

【标准答案】 Gateway统一鉴权方案:

1. 过滤器实现鉴权:

java
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取Token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        // 2. 校验Token(调用认证服务或本地校验JWT)
        if (!validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        // 3. 解析用户信息并透传给下游服务
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-User-Id", getUserId(token))
            .build();
        
        return chain.filter(exchange.mutate().request(request).build());
    }
    
    @Override
    public int getOrder() {
        return -100; // 优先级高,先执行
    }
}

Token传递方案:

方案一:JWT无状态传递

  • Gateway校验JWT签名后,解析用户信息放入请求头
  • 下游服务从请求头获取,无需再校验
  • 优点:无状态,性能好

方案二:Token透传

  • Gateway校验Token后,原样传递Token给下游
  • 下游服务自己解析Token
  • 优点:下游服务有完整控制权

方案三:内部Token

  • Gateway校验外部Token后,生成内部Token(如内网JWT)
  • 内部Token在服务间传递,有效期短
  • 优点:内外网隔离,安全性高

生产安全要点:

  • 内网服务间调用不暴露公网,可简化鉴权
  • 敏感操作需要二次校验(如修改密码)
  • Token过期后使用Refresh Token换取新Token
  • 记录审计日志,追踪每次请求的用户信息

【面试题】9. RocketMQ消息积压如何处理?消费者如何动态扩容? ​

【标准答案】 消息积压诊断:

1. 查看积压情况

bash
# 查看消费者组积压
mqadmin consumerProgress -g consumer_group_name

2. 分析积压原因

  • 消费者处理能力不足(CPU、IO瓶颈)
  • 消费逻辑有慢操作(如同步调用第三方接口)
  • 消费者实例宕机
  • 消息量突然暴增(如促销活动)

处理方案:

方案一:消费者扩容

  • RocketMQ基于Queue分片,消费者实例数不能超过Queue数
  • 扩容前先增加Topic的Queue数量(动态生效)
  • 然后增加消费者实例数
  • 注意:消费者数=Queue数时,再增加实例无效

方案二:临时提高消费速度

java
// 调整消费者线程数
consumer.setConsumeThreadMax(100);
consumer.setConsumeThreadMin(50);
// 调整批量消费数量
consumer.setConsumeMessageBatchMaxSize(50);

方案三:降级快速消费

  • 临时跳过非核心逻辑(如日志记录、数据同步)
  • 先消费完积压消息,再异步补数据

方案四:新建临时消费者

  • 创建新的Consumer Group,订阅相同Topic
  • 新消费者只负责消费积压消息,写入临时存储
  • 原消费者继续正常消费新消息
  • 积压消费完后,下线临时消费者

预防措施:

  • 设置消息TTL,超时自动丢弃或转死信队列
  • 监控消费延迟,设置告警阈值(如积压超过1万条)
  • 消费逻辑解耦,耗时操作异步处理
  • 压测评估消费者容量,预留扩容空间

【面试题】10. 微服务链路追踪中,TraceId和SpanId如何传递?对性能有什么影响? ​

【标准答案】 TraceId/SpanId传递机制:

1. 传递流程

请求进入 → Gateway生成TraceId → 
放入HTTP Header(X-Trace-Id)→ 
下游服务从Header读取 → 创建子Span → 
服务间调用继续透传 → 完成整条链路

2. Spring Cloud Sleuth实现

  • 自动注入RestTemplate、Feign、Gateway的拦截器
  • 无需手动编码,透明传递

3. 跨进程传递格式:

X-B3-TraceId: 1234567890123456  (16/32位)
X-B3-SpanId: 2345678901234567
X-B3-ParentSpanId: 3456789012345678
X-B3-Sampled: 1  (是否采样)

Span结构:

  • 一个请求在一个服务中的处理就是一个Span
  • Span包含:开始时间、耗时、服务名、操作名、Tags、Logs

性能影响分析:

影响点:

  1. 数据采集开销:每次调用创建Span,记录时间戳
  2. 网络传输开销:Trace数据上报到追踪系统(Zipkin/SkyWalking)
  3. 存储开销:链路数据量大,需要大量存储

优化策略:

1. 采样率控制

yaml
spring:
  sleuth:
    sampler:
      probability: 0.1  # 采样10%
  • 生产环境低采样率(1%-10%),问题排查时调高或全量

2. 异步上报

  • Span数据先写入本地队列,异步批量上报
  • 不阻塞业务线程

3. 数据压缩

  • Span数据用Thrift或Protobuf序列化
  • 减少网络传输量

4. 数据保留策略

  • Zipkin默认保留7天
  • SkyWalking支持动态调整保留周期

生产建议:

  • 核心链路(下单、支付)全量追踪
  • 非核心链路(日志上报)低采样
  • 监控系统自身性能,避免追踪系统成为瓶颈

生成时间: 2026-05-21 23:01 文件路径: /Users/pika/fsf/project/fsf-lunar-base/note/10-面试题/SpringCloud微服务面试题_20260521_2301.md