Skip to content

SpringCloud微服务架构面试题库 ​

生成时间:2026-05-22 22:41


【面试题】1. Nacos作为注册中心同时支持AP和CP模型,它是怎么切换的?什么场景该用哪种? ​

【标准答案】Nacos默认使用AP模式(临时实例+Distro协议),当服务实例是临时实例时,采用心跳检测,数据不走Raft一致性,优先保证可用性。当你把实例注册为持久化实例(permanent instance)时,Nacos切换到CP模式,使用Raft协议保证数据强一致性。实际选型上:业务服务用AP,因为服务挂了不影响数据一致性,优先保证注册中心可用;数据库主从这类有状态服务用CP,因为注册信息必须准确,否则可能导致写请求打到错误的节点。切换方式很简单,临时实例是默认行为,持久化实例通过ephemeral=false配置即可。

【面试题】2. Sentinel的滑动窗口限流算法是怎么实现的?和令牌桶、漏桶有什么区别? ​

【标准答案】Sentinel默认使用滑动窗口算法:把时间窗口分成多个小格子(默认500ms一个),每个格子记录通过请求数,滑动时只统计当前窗口内的格子总和。窗口滑动意味着旧格子被丢弃、新格子加入,所以统计更平滑,不会像固定窗口那样在窗口边界出现2倍突发流量。令牌桶是匀速生成令牌、允许突发(桶里有积累的令牌就能瞬间消费),适合允许短时突发的场景;漏桶是匀速流出、严格平滑,不管来多少请求都匀速放行。总结:滑动窗口统计精准无边界问题,令牌桶允许突发,漏桶严格匀速。Sentinel选滑动窗口是因为它在限流判断上最精准,且实现轻量。

【面试题】3. Seata的AT模式为什么能做到对业务代码零侵入?它的全局锁机制会不会成为性能瓶颈? ​

【标准答案】AT模式零侵入的核心在于Seata自动拦截SQL、自动生成回滚日志(undo_log)。一阶段:业务SQL执行后,Seata拦截并解析SQL,自动查询修改前数据,生成before-image和after-image写入undo_log表,然后一起提交本地事务。二阶段提交直接异步清理undo_log;二阶段回滚则根据undo_log反向补偿。全局锁机制:一阶段本地事务提交后,Seata会向TC注册全局锁(锁定修改的行),其他全局事务要等锁释放才能修改同一行。全局锁确实会增加等待,但粒度是行级锁,且只在全局事务期间持有,提交/回滚后立即释放。实际性能影响取决于热点数据冲突频率,如果全局事务很少操作同一行,瓶颈几乎不存在。极端热点场景可以改用TCC模式,业务自己控制锁粒度。

【面试题】4. Spring Cloud Gateway的过滤器链和Zuul有什么区别?如何用Gateway实现灰度发布? ​

【标准答案】Gateway基于WebFlux+Netty,非阻塞异步模型;Zuul 1.x是Servlet同步阻塞模型。Gateway过滤器分三种:GatewayFilter(针对特定路由)、GlobalFilter(全局生效)、GatewayFilterChain(责任链模式执行)。执行顺序靠getOrder()控制,Pre阶段做鉴权/限流/路由前处理,Post阶段做响应改写/日志记录。灰度发布实现:在GlobalFilter中读取请求头(如gray-tag: v2),或根据用户ID/地域做路由决策,然后通过ServerWebExchange修改GATEWAY_ROUTE_ATTR属性,动态切换到灰度版本的路由URI。配合Nacos配置中心,灰度路由规则可以热更新,不需要重启网关。核心代码就是exchange.getAttributes().put(ServerWebExchange.GATEWAY_ROUTE_ATTR, newRoute)。

【面试题】5. OpenFeign的超时和重试机制怎么配置?如何避免重试导致的接口重复执行问题? ​

【标准答案】OpenFeign超时分两级:connectTimeout(建立连接超时,默认10s)和readTimeout(读取响应超时,默认60s)。配置方式:全局配置在application.yml里设feign.client.config.default.connectTimeout/readTimeout;指定服务配置用feign.client.config.<service-name>.xxx覆盖。重试默认关闭(Retryer.NEVER_RETRY),开启需自定义Retryer。避免重试导致重复执行的关键:写接口(POST/PUT)默认不重试,只对读接口(GET)开启重试。如果业务上必须重试写接口,那接口必须做幂等设计——通过唯一请求ID(RequestId)去重,或用数据库唯一约束保证不会重复写入。实际项目中推荐:读接口开重试+超时短一些,写接口关重试+靠上游补偿机制处理失败。

【面试题】6. Redis分布式锁用Redisson实现时,看门狗机制是怎么工作的?什么情况下会失效? ​

【标准答案】Redisson加锁时如果不指定leaseTime,默认锁30秒自动释放,同时启动看门狗(Watchdog):每10秒(lockWatchdogTimeout/3)自动续期,把锁的TTL重置为30秒。续期是异步执行的,通过Netty的时间轮定时任务实现。只要持有锁的客户端线程还活着且没主动释放,看门狗就会一直续期。失效场景:(1)手动指定了leaseTime,看门狗不启动,锁到期自动释放;(2)客户端进程崩溃(OOM、kill -9),看门狗线程死了,锁30秒后自动释放——这是预期行为,正好避免死锁;(3)Redis主从切换时锁可能丢失——主节点加锁成功但未同步到从节点就宕机,从升主后锁不存在。解决主从切换问题用RedLock:向多个独立Redis节点加锁,半数以上成功才算获取锁。

【面试题】7. Sleuth的TraceId和SpanId是怎么在服务间传递的?如果经过Kafka消息队列,链路信息会断吗? ​

【标准答案】HTTP调用场景:Sleuth通过HTTP Header传递链路信息,默认Header名是X-B3-TraceId、X-B3-SpanId、X-B3-ParentSpanId、X-B3-Sampled(B3协议)。下游服务从Header中提取这些值,继续挂载到后续请求中。Kafka场景:Sleuth会自动把TraceId/SpanId注入到Kafka消息的Header中(b3字段),消费者从消息Header中提取,链路不会断。但有个前提:必须使用Spring Cloud Sleuth自动装配的Kafka Producer/Consumer,自己手动创建的Producer不走Sleuth拦截,链路就会断。如果是RocketMQ,Sleuth同样通过消息属性传递,原理一致。总之,只要用的是Spring Cloud Stream整合的MQ组件,链路都是自动打通的。

【面试题】8. Spring Cloud Config和Nacos Config在配置热更新上有什么区别?Config Server怎么保证高可用? ​

【标准答案】Spring Cloud Config热更新需要客户端主动触发:要么用/actuator/refresh端点手动刷新,要么配合Spring Cloud Bus(通过MQ广播刷新事件),配置变更后批量通知所有客户端刷新。Nacos Config天然支持热更新:配置变更后Nacos Server主动通过长轮询(Long Polling)通知客户端,客户端自动刷新,不需要Bus也不需要手动触发。Config Server高可用方案:(1)将Config Server注册到Eureka/Nacos,客户端通过服务发现访问Config Server,部署多个实例自然负载均衡;(2)Config Server后端Git仓库做高可用(GitHub/GitLab集群);(3)Git仓库本地clone做兜底,Config Server启动时拉取一份本地缓存,Git挂了还能从本地读取。Nacos Config本身集群部署就行,自带高可用,不需要这些额外手段。

【面试题】9. 微服务场景下OAuth2+JWT的认证授权流程怎么设计?Token在服务间怎么传递? ​

【标准答案】整体架构:API网关做统一认证入口,认证服务(Auth Server)负责签发Token。流程:(1)客户端带用户名密码请求网关/login路由;(2)网关转发到Auth Server,Auth Server校验后签发JWT Access Token + Refresh Token返回;(3)后续请求客户端在Header带Authorization: Bearer <JWT>,网关校验JWT签名和过期时间,通过后路由到下游服务。服务间Token传递:网关校验通过后,把用户信息(userId、roles等)放到请求Header中透传给下游服务,比如X-User-Id、X-User-Roles。下游服务间内部调用(Feign)通过Feign拦截器自动把Header透传下去。内部服务之间不需要再校验JWT,信任网关已经做了鉴权,简化内部调用链路。Refresh Token机制:Access Token有效期短(如30分钟),Refresh Token有效期长(如7天),Access Token过期后用Refresh Token无感刷新,避免用户重复登录。

【面试题】10. Kubernetes部署Spring Cloud微服务时,Nacos的注册IP问题怎么解决?Service Mesh和Spring Cloud治理能力有重叠吗? ​

【标准答案】Nacos注册IP问题:Pod的IP是动态的,且容器内InetAddress拿到的可能是Pod内网IP,集群外部访问不到。解决方案:(1)配置spring.cloud.nacos.discovery.ip为Pod的真实可达IP;(2)用Headless Service + spring.cloud.nacos.discovery.ip-type=hostname,让Nacos注册的是Service名而非Pod IP;(3)推荐用Spring Cloud Kubernetes,直接对接K8s Service发现机制,不走Nacos注册,由K8s Service做负载均衡和路由。Service Mesh vs Spring Cloud:确实有重叠。Istio的服务发现、负载均衡、熔断限流、链路追踪和Spring Cloud的Nacos+Ribbon+Sentinel+Sleuth功能重叠。区别在于:Service Mesh是基础设施层(Sidecar代理),对应用无侵入;Spring Cloud是应用层SDK,需要改代码。趋势是:新项目可以Service Mesh为主、减少SDK依赖;老项目迁移成本大,Spring Cloud仍实用。两者可以共存,但没必要同一功能搞两套。