SpringCloud微服务架构面试题库
生成时间:2026-05-22 21:50
本轮 SpringCloud微服务架构面试题库(带答案)
【面试题】1. Nacos作为注册中心,如何保证服务实例列表的实时性?服务下线后多久会被其他服务感知到?
【标准答案】 这个我分两个层面回答:
第一,Nacos感知机制 Nacos采用客户端心跳+服务端主动推送的双保险机制。服务实例每5秒发送一次心跳,服务端15秒没收到心跳标记为不健康,30秒还没收到就剔除。同时,Nacos会主动推送给订阅的客户端,保证实时性。
第二,优化策略 生产环境我们会调整参数:心跳间隔缩短到3秒,不健康阈值10秒,剔除阈值20秒,这样最快10秒就能感知到故障。
第三,实际应用 我们线上的经验是,配合健康检查接口,让Nacos更精准判断服务是否真正可用,而不是只看心跳。这样既保证实时性,又避免误剔除。
【面试题】2. Sentinel和Hystrix在熔断机制上有什么本质区别?生产环境选哪个?
【标准答案】 这个我对比说明:
核心区别
- Hystrix:基于线程池隔离,每个资源分配独立线程池,资源隔离彻底但线程开销大
- Sentinel:基于信号量+滑动窗口,轻量级,支持更细粒度的流控
生产选型 我们现在首选Sentinel,原因有三个:
- 阿里出品,社区活跃,Spring Cloud Alibaba生态集成好
- 控制台更强大,实时监控、规则动态下发、集群流控都支持
- 资源消耗小,高并发场景更稳定
实践经验 Sentinel的规则配置我们用Nacos持久化,避免重启丢失。熔断阈值我们根据服务SLA来定,核心服务慢调用比例超过50%触发熔断,非核心服务30%就熔断。
【面试题】3. Spring Cloud Gateway如何实现灰度发布?具体落地方案是什么?
【标准答案】 这个我们实战过,方案如下:
第一,灰度策略 通过请求头或参数携带版本标识,比如version=v2,Gateway根据路由规则将流量打到对应版本的服务实例。
第二,实现方案 核心是三点:
- 服务注册时携带metadata标签(如version=v1/v2)
- Gateway自定义Filter读取请求头,匹配metadata
- 使用Spring Cloud Gateway的Weight路由谓词控制流量比例
第三,具体代码 我们自定义了GrayscaleFilter,从Header提取version,结合Nacos的元数据过滤实例,用Ribbon的ZoneAvoidanceRule变体实现版本路由。
第四,生产实践 实际灰度流程:先切5%流量观察监控指标,无异常逐步扩大到20%、50%、100%。配合Prometheus告警,异常时自动回滚。
【面试题】4. Seata的AT模式为什么能实现无侵入的分布式事务?它的工作原理是什么?
【标准答案】** AT模式核心是自动补偿,开发者无需写回滚逻辑,框架自动生成。
工作原理三步走
- 一阶段提交:执行业务SQL,生成前后镜像(before/after image),写入undo_log表,直接提交本地事务
- 二阶段提交:删除undo_log,释放全局锁
- 二阶段回滚:读取undo_log,反向生成SQL恢复数据
关键技术
- 全局锁:防止并发写冲突,保证隔离性
- undo_log:记录数据快照,回滚时用前镜像覆盖
生产经验 AT模式适合大多数业务场景,我们要求:
- 每个库必须建undo_log表
- 业务表必须有主键
- 避免大事务,控制分支事务在10秒内
AT模式性能比TCC低10%,但开发效率高5倍,我们核心链路用TCC,普通业务用AT。
【面试题】5. Redis分布式锁如何解决锁续期和锁释放问题?Redisson是怎么做的?
【标准答案】** 这个问题很关键,我分开讲:
锁续期问题 普通锁设置过期时间后,业务还没执行完锁就过期了,会引发并发问题。Redisson用看门狗(Watchdog)机制解决,后台线程每10秒(默认过期时间30秒的1/3)自动续期,业务执行完主动释放才停止续期。
锁释放问题 客户端A获取锁,业务卡住,锁过期自动释放,客户端B获取锁执行。A恢复后直接释放B的锁——这是经典误删问题。Redisson用Lua脚本保证原子性:释放时检查锁的value是否是当前线程持有,是才删除。
RedLock方案 主从架构下,主节点加锁成功但未同步从节点就宕机,会丢锁。Redisson的RedLock算法在多个Redis实例上加锁,超过半数成功才算获取成功。
生产配置 我们用Redisson,配置3个Redis节点,锁等待时间5秒,租期30秒,看门狗自动续期。关键是finally块一定要释放锁。
【面试题】6. OpenFeign的超时和重试机制如何配置?如何避免重试风暴?
【标准答案】** 这个要谨慎配置,我讲实战方案:
超时配置 分两层:
- Feign层:
feign.client.config.default.connectTimeout=5000,readTimeout=10000 - Ribbon层:
ribbon.ConnectTimeout=5000,ReadTimeout=10000
Spring Cloud 2020+版本优先用Feign配置。
重试配置 默认重试机制可能引发雪崩,我们这样做:
- 关闭Feign默认重试:
feign.client.config.default.retryer=NEVER_RETRY - 关键接口不重试,用熔断兜底
- 非关键接口用自定义重试器:最多重试2次,间隔1秒
避免重试风暴 核心措施三个:
- 幂等性设计:所有写操作必须幂等,用唯一请求ID去重
- 重试+限流:Sentinel配置QPS阈值,超限直接拒绝
- 熔断降级:错误率超过阈值触发熔断,避免级联失败
经验教训 我们曾遇到重试风暴,改用自定义Retryer后问题解决。原则是:核心链路不重试,非核心链路有限重试,所有接口必须幂等。
【面试题】7. Spring Cloud Config如何实现配置热更新?Nacos Config相比有什么优势?
【标准答案】** 对比分析:
Spring Cloud Config热更新 基于Git的配置中心,热更新有两种方式:
- 手动刷新:POST请求
/actuator/refresh端点,触发配置重新加载 - Webhook自动化:Git提交触发Webhook,批量刷新服务实例
配置刷新粒度是@RefreshScope注解的Bean。
Nacos Config的优势 我们后来迁移到Nacos,原因有四个:
- 真正的实时推送:长轮询机制,配置变更秒级生效,无需手动触发
- 控制台友好:可视化编辑、历史版本、回滚一键完成
- 多环境管理:Namespace+Group隔离,比Config的profile更灵活
- 注册+配置一体化:一个组件解决两个问题,运维成本减半
热更新实战 用Nacos后,我们配置文件都加@RefreshScope,结合@NacosValue(autoRefreshed=true)实现字段级动态刷新。数据库连接池参数改了立即生效,不用重启服务。
【面试题】8. 微服务架构下,如何实现跨服务的链路追踪?TraceId如何传递?
【标准答案】** 这个我们用Sleuth+Zipkin实现,核心原理讲一下:
TraceId传递机制 Sleuth通过HTTP Header传递TraceId:
- 请求进入网关,网关生成TraceId,写入Header:
X-B3-TraceId - 服务A调用服务B时,RestTemplate/Feign拦截器自动从ThreadLocal读取TraceId,透传到下游
- 全链路共用一个TraceId,每个服务生成自己的SpanId,形成调用树
关键技术点
- ThreadLocal存储:MDC.put("traceId", traceId),日志自动打印TraceId
- 异步调用处理:线程池要用
ContextCopyingExecutor,Runnable/Callable要包装,否则丢失上下文 - 消息队列传递:MQ消息体携带TraceId,消费者读取后设置到当前上下文
生产实践 我们做了三件事:
- Zipkin用Elasticsearch存储,保留7天数据
- 采样率设置为20%,高并发场景避免性能损耗
- 日志统一格式:
[%X{traceId}] %msg,方便用ELK检索全链路日志
【面试题】9. Spring Cloud Gateway如何集成OAuth2+JWT实现统一认证授权?
【标准答案】** 这是我们生产环境的安全方案,我讲具体实现:
架构设计 Gateway作为统一认证入口,流程是:
- 用户登录 → Gateway转发到认证服务(OAuth2授权服务器)
- 认证成功 → 返回Access Token(JWT格式)
- 后续请求 → Gateway验证Token,解析用户信息,传递到下游微服务
Gateway集成步骤 核心是自定义全局过滤器JwtAuthFilter:
- 白名单路径(登录、公开接口)直接放行
- 其他请求从Header提取Token,调用认证服务验证接口
- 验证通过后,将用户ID、权限信息写入RequestHeader,转发到下游
Token传递 下游微服务用RequestHeaderAuthenticationFilter,从Header读取用户信息,设置到SecurityContext。
安全增强 我们加了三道防线:
- Token有效期2小时,Refresh Token 7天
- IP白名单+设备指纹,防止Token被盗用
- 敏感操作二次验证(短信验证码)
踩坑经验 JWT Token不要存敏感信息,只存用户ID,权限信息从Redis获取。避免Token泄露导致信息泄露。
【面试题】10. 消息队列在微服务架构中有哪些典型应用场景?如何保证消息不丢失?
【标准答案】** 这个结合我们实战经验讲:
三大典型场景
- 异步解耦:用户注册后发送欢迎邮件、短信,主流程同步执行,通知异步发送,响应时间从500ms降到100ms
- 削峰填谷:秒杀活动,请求先写MQ,后端服务按能力消费,数据库压力降低80%
- 最终一致性:分布式事务场景,订单服务创建订单后发消息,库存服务消费消息扣库存,失败后重试或补偿
消息不丢失的三道防线
- 生产端:启用确认机制(Confirm Callback),消息持久化成功才返回成功
- Broker端:消息持久化到磁盘,集群部署+副本同步,单节点宕机不丢数据
- 消费端:手动ACK,业务逻辑执行成功后再确认,失败则重试或死信队列
我们用RocketMQ的配置
- 生产者:
retryTimesWhenSendFailed=3,同步发送 - Broker:
flushDiskType=SYNC_FLUSH,brokerRole=SYNC_MASTER - 消费者:
messageModel=CLUSTERING,业务成功后调用ack()确认
死信处理 重试3次失败的消息进入死信队列,人工介入或定时任务补偿。我们建立了消息轨迹追踪,每条消息状态可查询。
本轮题目覆盖考点:
- 服务注册与发现(Nacos感知机制)
- 熔断限流(Sentinel vs Hystrix)
- API网关(灰度发布)
- 分布式事务(Seata AT模式)
- 分布式锁(Redisson实现)
- 服务调用(OpenFeign超时重试)
- 配置中心(Config vs Nacos)
- 链路追踪(TraceId传递)
- 微服务安全(OAuth2+JWT)
- 消息队列集成(消息可靠性)
生成说明:
- 题目类型:架构设计4题、场景实操3题、技术原理3题
- 难度分布:基础3题、进阶5题、高级2题
- 所有答案均为生产实战总结,简洁落地,避免堆砌术语