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):
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. 基于请求头的灰度
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, v22. 基于权重的灰度
predicates:
- Weight=user-service, 80 # 80%流量走v1版本3. 基于URL参数的灰度
predicates:
- Query=version, v24. 基于Cookie的灰度
predicates:
- Cookie=version, v2生产实践要点:
- 灰度策略组合:先用Cookie/Header做内部测试,确认无问题后逐步放权重
- 监控告警:灰度版本必须有独立的监控指标,实时观察错误率、响应时间
- 快速回滚:发现问题立即调整权重为0,所有流量切回稳定版本
- 全链路透传:灰度标识需要通过请求头在整个调用链透传(用Feign拦截器或Gateway过滤器)
完整灰度流程:
- 内部测试人员通过Header访问v2版本
- 验证通过后,开放5%流量给外部用户
- 观察监控指标,逐步提升到20%、50%、100%
- 全量后,下线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服务端一次性执行,不会被其他命令打断
为什么原子性重要:
# 错误写法(非原子)
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原理:
使用方式:
@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. 过滤器实现鉴权:
@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. 查看积压情况
# 查看消费者组积压
mqadmin consumerProgress -g consumer_group_name2. 分析积压原因
- 消费者处理能力不足(CPU、IO瓶颈)
- 消费逻辑有慢操作(如同步调用第三方接口)
- 消费者实例宕机
- 消息量突然暴增(如促销活动)
处理方案:
方案一:消费者扩容
- RocketMQ基于Queue分片,消费者实例数不能超过Queue数
- 扩容前先增加Topic的Queue数量(动态生效)
- 然后增加消费者实例数
- 注意:消费者数=Queue数时,再增加实例无效
方案二:临时提高消费速度
// 调整消费者线程数
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
性能影响分析:
影响点:
- 数据采集开销:每次调用创建Span,记录时间戳
- 网络传输开销:Trace数据上报到追踪系统(Zipkin/SkyWalking)
- 存储开销:链路数据量大,需要大量存储
优化策略:
1. 采样率控制
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