Skip to content

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

生成时间:2026-05-24 20:33


【面试题】1. Nacos作为注册中心,它的AP和CP模式怎么选择?底层原理是什么? ​

【标准答案】Nacos支持AP和CP两种模式切换,关键看业务对一致性的要求。

选择标准:

  • AP模式(可用性优先):适合临时实例,比如常规微服务。允许短暂的数据不一致,优先保证服务可用,适合对实时性要求不高但需要高可用的场景。
  • CP模式(一致性优先):适合持久化实例,比如数据库、配置中心等核心基础设施。必须保证数据强一致性,宁可短暂不可用也不返回错误数据。

底层原理: Nacos 1.x用Raft协议实现CP模式,Leader节点负责写操作,Follower同步日志达成一致;AP模式用Distro协议,每个节点独立处理读写,通过异步复制最终一致。Nacos 2.x重构后用自研的JRaft和Distro v2,性能更好。

面试加分点: 说一句"我们生产环境一般用AP模式,因为服务发现允许秒级延迟,但必须保证高可用",体现实际经验。


【面试题】2. Sentinel和Hystrix的熔断原理有什么区别?实际项目怎么选? ​

【标准答案】两者都是熔断降级,但设计理念和实现方式差异很大。

核心区别:

维度HystrixSentinel
隔离策略线程池/信号量隔离信号量隔离(默认)+ 并发线程数控制
熔断状态机三态:关闭→打开→半开三态:关闭→打开→半开,但支持更多规则
限流算法信号量计数QPS/并发线程数,支持滑动窗口、令牌桶、漏桶
动态规则需配置中心配合原生支持控制台动态推送
资源消耗线程池模式开销大轻量,无线程池开销

实际选择建议:

  • 新项目直接选Sentinel:功能更全(限流+熔断+热点参数限流+系统自适应保护),社区活跃,阿里维护。
  • 老项目用Hystrix:如果已经稳定运行,迁移成本高,可以继续用,但Hystrix已停止维护。
  • Resilience4j:如果追求轻量和函数式编程风格,可以选它,但功能不如Sentinel丰富。

面试加分点: "我们用Sentinel,配合Nacos做规则持久化,控制台可视化做得很好",体现实战经验。


【面试题】3. Spring Cloud Gateway如何实现灰度发布?具体方案是什么? ​

【标准答案】灰度发布核心是路由规则的动态控制,Gateway通过Filter和Predicate组合实现。

主流方案:

方案一:基于请求头的灰度

yaml
spring:
  cloud:
    gateway:
      routes:
        - id: service-v1
          uri: lb://user-service-v1
          predicates:
            - Path=/api/user/**
            - Header=X-Gray-Version, v1
        - id: service-v2
          uri: lb://user-service-v2
          predicates:
            - Path=/api/user/**
            - Header=X-Gray-Version, v2

方案二:基于权重的灰度 用Weight断言,比如90%流量走v1,10%走v2,观察稳定后逐步扩大。

方案三:基于注册中心元数据 服务注册时带上version标签,Gateway根据元数据路由,结合Nacos或Eureka的元数据功能。

生产级方案:

  1. Nacos配置中心存储灰度规则(版本、权重、白名单用户)
  2. Gateway动态刷新路由配置
  3. 监控指标对比(错误率、RT、QPS)决定是否扩大灰度比例
  4. 出问题秒级回滚

面试加分点: "我们用Nacos配置中心配合Gateway,实现分钟级灰度发布,有问题一键回滚",结合实际场景更打动人。


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

【标准答案】两者都是分布式事务解决方案,但实现机制和适用场景完全不同。

AT模式(Automatic Transaction):

  • 原理:基于数据库本地事务+全局锁,第一阶段执行本地事务并记录undo_log,第二阶段异步提交或回滚。
  • 优点:零侵入,不需要改业务代码,框架自动处理。
  • 缺点:依赖数据库事务,有全局锁竞争,高并发性能下降明显。
  • 适用场景:普通业务、对一致性要求不是特别高、能接受短暂脏读。

TCC模式(Try-Confirm-Cancel):

  • 原理:业务代码显式编写三个阶段,Try预留资源、Confirm提交、Cancel回滚。
  • 优点:资源锁定粒度小,性能好,最终一致性可控。
  • 缺点:代码侵入性强,需要自己写补偿逻辑,开发成本高。
  • 适用场景:高并发核心业务、资源竞争激烈、需要精确控制一致性的场景(如库存、账户)。

选择建议:

  • 80%场景用AT模式,开发效率高,够用。
  • 核心资金/库存场景用TCC,性能好、控制细。
  • 跨公司/跨平台用Saga模式或本地消息表。

面试加分点: "我们订单扣库存用TCC,普通订单状态更新用AT,区分核心和非核心业务",体现架构思维。


【面试题】5. Redis分布式锁用什么实现?Redisson和SET NX EX有什么区别? ​

【标准答案】Redis分布式锁主流两种实现,Redisson是生产级推荐方案。

SET NX EX方式(原生Redis命令):

bash
SET lock:key unique_value NX EX 30
  • 优点:简单直接,一条命令原子执行。
  • 缺点:
    • 锁续期需要自己实现(看门狗机制)
    • 无法实现可重入锁
    • 集群模式下可能多个节点同时获得锁(AP模型的坑)
    • 解锁需要Lua脚本保证原子性

Redisson方式(框架封装):

java
RLock lock = redisson.getLock("myLock");
lock.lock(); // 自动续期
lock.unlock();
  • 优点:
    • 自动续期(Watchdog看门狗,默认30秒,后台线程每10秒续期)
    • 支持可重入锁
    • 支持RedLock(集群模式锁安全)
    • 支持公平锁、读写锁、闭锁等丰富锁类型
    • 解锁原子性保证
  • 缺点:框架依赖,学习成本稍高。

生产环境建议:

  • 单机Redis:直接用Redisson。
  • Redis Cluster/Sentinel:用Redisson的RedLock模式保证安全性。
  • 超高并发场景:考虑Zookeeper分布式锁,CP模型强一致更安全。

面试加分点: "我们用Redisson,它的看门狗机制很好用,不用操心锁过期被别人抢走",说明踩过坑有经验。


【面试题】6. OpenFeign超时重试怎么配置?为什么有时候会触发多次重试? ​

【标准答案】OpenFeign的超时配置分两层,理解清楚才能避免坑。

配置方式:

yaml
feign:
  client:
    config:
      default:
        connectTimeout: 5000  # 连接超时5秒
        readTimeout: 10000    # 读取超时10秒

重试机制: OpenFeign默认使用Retryer.Default,最多重试5次,间隔从100ms开始指数退避。

为什么会多次重试?

  1. 默认重试器生效:没配置时,超时或网络异常会自动重试。
  2. Ribbon重试叠加:如果用了Ribbon做负载均衡,Ribbon本身也有重试逻辑,可能和Feign重试叠加,导致实际调用次数=Feign重试×Ribbon重试。
  3. 服务端慢响应:readTimeout触发后,客户端已经重试,但服务端请求还在队列里,造成重复请求。

生产配置建议:

yaml
feign:
  client:
    config:
      default:
        connectTimeout: 3000
        readTimeout: 5000
  retryer: feign.Retryer.NEVER_RETRY  # 关闭Feign层重试

ribbon:
  MaxAutoRetries: 1          # 同实例重试1次
  MaxAutoRetriesNextServer: 1  # 切换实例重试1次
  OkToRetryOnAllOperations: false  # 只重试GET,不重试POST

面试加分点: "我们关闭Feign重试,只用Ribbon层重试,并且只对GET请求重试,幂等性更可控",体现对重试机制的深入理解。


【面试题】7. 微服务链路追踪怎么做?TraceId和SpanId是怎么传递的? ​

【标准答案】链路追踪是微服务可观测性的核心,TraceId和SpanId的传递机制是关键。

主流方案:

  • Sleuth + Zipkin:Spring Cloud生态默认方案,集成简单,适合中小规模。
  • SkyWalking:性能好,无侵入,可视化强,适合大规模生产。
  • Micrometer Tracing + Jaeger:Sleuth的替代品,Spring Boot 3.x官方推荐。

TraceId/SpanId传递原理:

  1. 入口请求:Gateway或第一个服务生成TraceId(全局唯一,贯穿整个调用链)和SpanId(当前服务标识)。
  2. HTTP传递:通过HTTP Header传递,约定Header名称:
    • X-Trace-Id 或 X-B3-TraceId
    • X-Span-Id 或 X-B3-SpanId
    • X-Parent-SpanId
  3. 跨服务调用:OpenFeign/RestTemplate自动拦截器把Header透传到下游。
  4. 异步场景:线程池需要手动传递MDC(Mapped Diagnostic Context),或用@Async配合TaskDecorator自动传递。

关键代码:

java
// 异步线程池传递TraceId
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(MDC.getCopyOfContextMap(), () -> {
    // 子线程自动继承父线程TraceId
});

面试加分点: "我们用SkyWalking,异步场景封装了TaskDecorator,TraceId透传问题踩过坑",展示实战经验。


【面试题】8. Nacos配置中心怎么做热更新?多环境配置怎么管理? ​

【标准答案】Nacos配置中心的核心价值是热更新,多环境管理是生产必备。

热更新原理:

  1. 客户端启动时建立长轮询连接(默认30秒)。
  2. 配置变更后,Nacos推送变更通知。
  3. 客户端收到通知,拉取最新配置。
  4. @RefreshScope注解的Bean会重新创建,注入新值。

热更新配置:

java
@RestController
@RefreshScope  // 关键注解,配置变更自动刷新
public class ConfigController {
    @Value("${app.config.value}")
    private String configValue;
}

多环境管理方案:

方案一:Namespace隔离

namespace: dev  -> 开发环境
namespace: test -> 测试环境
namespace: prod -> 生产环境

每个Namespace完全独立,配置隔离干净。

方案二:Group分组

namespace: public
  group: DEFAULT_GROUP -> 默认配置
  group: DEV_GROUP -> 开发配置
  group: PROD_GROUP -> 生产配置

同一Namespace下用Group区分。

方案三:Data ID后缀

application-dev.yaml
application-test.yaml
application-prod.yaml

Spring Boot原生Profile机制,Nacos支持。

生产推荐: Namespace隔离环境,Group区分项目或模块,层次清晰,权限好控制。

面试加分点: "我们用Namespace隔离环境,配合权限控制,开发和生产完全隔离",说明有生产治理意识。


【面试题】9. Spring Cloud Gateway如何做统一鉴权?JWT Token怎么传递到下游服务? ​

【标准答案】Gateway作为流量入口,统一鉴权是标配,JWT Token传递是关键环节。

统一鉴权方案:

方案一:Gateway Filter鉴权

java
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isEmpty(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 验证JWT
        Claims claims = JwtUtil.parseToken(token);
        // 把用户信息透传到下游
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-User-Id", claims.get("userId").toString())
            .header("X-User-Name", claims.get("username").toString())
            .build();
        return chain.filter(exchange.mutate().request(request).build());
    }
    
    @Override
    public int getOrder() {
        return -100; // 优先执行
    }
}

方案二:集成OAuth2 用Spring Security + OAuth2资源服务器,Gateway做Token校验,下游服务无状态。

JWT Token传递到下游:

  1. 透传Token:Gateway不做解析,直接把Header传给下游,下游服务自己校验。
  2. 解析后传递:Gateway解析JWT,提取用户信息放到Header(如X-User-Id),下游服务直接使用,不用再解析。

生产建议:

  • 高频接口用方案二(解析后传递),减少下游重复校验开销。
  • 敏感操作用方案一(透传Token),下游二次校验保证安全。

面试加分点: "我们用方案二,Gateway解析JWT后把用户ID放到Header透传,下游服务不用再解析,性能更好",体现性能优化意识。


【面试题】10. 消息队列如何保证消息不丢失?Spring Cloud Stream怎么实现可靠消费? ​

【标准答案】消息可靠性是分布式系统的难点,需要从生产端、Broker端、消费端三方面保证。

消息不丢失方案:

1. 生产端保证

  • 开启确认机制(ACK):消息发送后等待Broker确认。
  • 消息持久化:发送前先落库,确认成功后删除,失败重试或告警。
java
// RocketMQ示例
producer.send(message, new SendCallback() {
    @Override
    public void onSuccess(SendResult result) {
        // 确认成功,删除本地消息表记录
    }
    @Override
    public void onException(Throwable e) {
        // 重试或告警
    }
});

2. Broker端保证

  • 开启同步刷盘(性能换可靠性)。
  • 主从同步复制,主节点挂了从节点有数据。
  • RocketMQ默认异步刷盘+异步复制,可配置SYNC_FLUSH和SYNC_MASTER。

3. 消费端保证

  • 关闭自动提交offset,业务处理成功后手动提交。
  • 幂等性设计:消息ID去重,防止重复消费。
java
@StreamListener(Sink.INPUT)
public void handleMessage(Message<String> message) {
    String messageId = message.getHeaders().getId().toString();
    if (redisTemplate.opsForValue().setIfAbsent("msg:" + messageId, "1", 1, TimeUnit.DAYS)) {
        // 首次消费,处理业务
        processBusiness(message.getPayload());
    } else {
        // 重复消息,跳过
        log.warn("重复消息: {}", messageId);
    }
    // 手动确认
    acknowledgment.acknowledge();
}

Spring Cloud Stream配置:

yaml
spring:
  cloud:
    stream:
      rocketmq:
        bindings:
          input:
            consumer:
              enable: true
              orderly: true  # 顺序消费
              messageModel: CLUSTERING  # 集群模式
      bindings:
        input:
          group: order-group  # 同一group保证负载均衡+不重复消费
          consumer:
            auto-commit-offset: false  # 关闭自动提交

面试加分点: "我们用本地消息表+定时任务补偿,保证最终一致性,RocketMQ事务消息也用过",说明有完整解决方案经验。


总结 ​

本轮面试题覆盖:

  • 服务注册与发现:Nacos AP/CP模式(题1)
  • 熔断限流降级:Sentinel vs Hystrix(题2)
  • API网关:Gateway灰度发布(题3)、统一鉴权与Token传递(题9)
  • 分布式事务:Seata AT/TCC模式(题4)
  • 分布式锁:Redis分布式锁与Redisson(题5)
  • 服务调用:OpenFeign超时重试(题6)
  • 链路追踪:TraceId/SpanId传递(题7)
  • 配置中心:Nacos热更新与多环境管理(题8)
  • 消息队列:消息可靠性保证(题10)

每道题都包含:技术原理+对比分析+生产经验+面试加分话术,适合冲刺面试。