Spring Cloud 高频面试题详解(含代码示例与深度解析)

Spring Cloud 高频面试题详解(含代码示例与深度解析)

本文旨在帮助求职者系统性地复习和准备 Spring Cloud 相关面试,涵盖了从核心组件到高级用法的常见问题,并辅以代码示例和表格对比,助你轻松拿下面试。


1. 什么是 Spring Cloud?它与 Spring Boot 有什么关系?

Spring Cloud 是一套分布式系统解决方案的规范集合,它基于 Spring Boot 提供了快速构建分布式系统中常见模式的工具(例如:配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话和集群状态)。

关系与区别

  • Spring Boot:专注于快速、方便地开发单个微服务,提供了自动配置、起步依赖等特性,简化了独立服务的开发。
  • Spring Cloud:专注于微服务架构的协调与治理,它将多个 Spring Boot 应用程序整合起来,为它们提供分布式环境下的能力。

简单比喻

Spring Boot 像是制造汽车的工厂,能快速造出许多功能独立的汽车(微服务)。而 Spring Cloud 像是交通管理系统,负责所有汽车之间的通信、调度、交通规则(治理),确保整个交通网络(微服务系统)有序、可靠地运行。


2. 服务发现:Eureka 和 Nacos 的区别与选型?

服务发现是微服务架构的基石,客户端通过它来定位网络上的服务实例。

Eureka 示例与原理

1. Eureka Server (服务端)

# application.yml
server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false # 自身不注册到Eureka
    fetch-registry: false       # 不获取注册信息
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

2. Eureka Client (客户端 - 服务提供者)

# application.yml
spring:
  application:
    name: user-service # 应用名称,以后就用这个名字来调用服务
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/ # 注册中心的地址

Eureka vs Nacos 对比表

特性EurekaNacos
核心功能服务注册与发现服务注册与发现、动态配置管理
一致性协议AP (保证可用性和分区容错性)AP + CP 模式切换 (同时满足一致性和可用性)
健康检查Client Beat (客户端心跳)Server Beat (服务端主动检测) / Client Beat
负载均衡需集成 Ribbon集成 Ribbon,自身也提供
配置中心不支持原生支持,功能强大
管理界面功能相对简单功能丰富,集成配置管理
社区生态Netflix 已停止维护,进入维护模式阿里巴巴开源,社区活跃,持续更新

选型建议

  • 老项目或简单场景:Eureka 足够。
  • 新项目强烈推荐 Nacos:它集注册中心和配置中心于一体,功能更全面,性能更好,是目前的主流选择。

3. 负载均衡:Ribbon 和 LoadBalancer 的区别?

Spring Cloud 提供了客户端负载均衡器。

Ribbon (已进入维护模式)

Ribbon 是一个客户端负载均衡器,通过与服务发现组件(如 Eureka)集成,获取所有服务实例列表,然后在客户端采用特定策略(如轮询、随机)进行调用。

// 在 RestTemplate 上使用 @LoadBalanced 注解即可开启 Ribbon
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced // 这个注解让 RestTemplate 具有了客户端负载均衡的能力
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

// 使用时直接使用服务名代替IP地址
@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    public User findOrderByUserId(Long userId) {
        // 直接使用服务名 "order-service",Ribbon 会将其解析为实际地址并负载均衡
        String url = "http://order-service/orders/" + userId;
        return restTemplate.getForObject(url, User.class);
    }
}

Spring Cloud LoadBalancer (官方新标准)

由于 Ribbon 停止维护,Spring Cloud 官方推出了 LoadBalancer 作为其替代品。

如何使用

  1. 引入依赖 (通常包含在 spring-cloud-starter-loadbalancer 中)
  2. 同样的代码:上述 RestTemplate 的代码无需改动,只需移除 Ribbon 依赖,引入 LoadBalancer 依赖即可无缝切换。
  3. 支持 Reactive:完美支持 WebClient 进行响应式编程。
// 使用 WebClient + LoadBalancer
@Service
public class UserService {

    @Autowired
    private WebClient.Builder webClientBuilder;

    public Mono<User> findOrderByUserId(Long userId) {
        return webClientBuilder.build()
                .get()
                .uri("http://order-service/orders/" + userId) // 使用服务名
                .retrieve()
                .bodyToMono(User.class);
    }
}

结论

  • 新项目务必使用 Spring Cloud LoadBalancer,它是官方钦定的未来。
  • 老项目如果使用 Ribbon,建议规划迁移。

4. 服务调用:Feign 和 OpenFeign?

Feign 是一个声明式的 Web Service 客户端,它的目的是让编写 Java HTTP 客户端变得更简单。使用 Feign 时,只需要创建一个接口并加上注解即可。

OpenFeign 是 Spring Cloud 在 Feign 的基础上支持了 Spring MVC 注解,并整合了 Ribbon 和 Eureka(现在主要是 LoadBalancer),从而大大简化了服务间调用的开发。

示例:如何用 OpenFeign 优雅地调用服务

  1. 添加依赖spring-cloud-starter-openfeign

  2. 启动类开启 Feign

    @SpringBootApplication
    @EnableFeignClients // 开启 Feign 客户端功能
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
  3. 声明接口

    // 声明这是一个 Feign 客户端,并指定要调用的服务名
    @FeignClient(name = "order-service")
    public interface OrderServiceClient {
    
        // 定义接口方法,就像在写 Spring MVC 的 Controller 一样
        @GetMapping("/orders/{orderId}") // 映射 order-service 中的接口路径
        Order getOrderById(@PathVariable("orderId") Long orderId);
    
        @PostMapping("/orders")
        Order createOrder(@RequestBody Order order);
    }
    
  4. 像调用本地服务一样使用

    @Service
    public class UserService {
    
        // 直接注入 Feign 客户端接口
        @Autowired
        private OrderServiceClient orderServiceClient;
    
        public User getUserWithOrders(Long userId) {
            User user = userRepository.findById(userId);
            // 直接调用接口方法,Feign 会帮你处理HTTP请求、负载均衡、服务发现等所有底层细节
            List<Order> orders = orderServiceClient.getOrdersByUserId(userId);
            user.setOrders(orders);
            return user;
        }
    }
    

核心优势接口化、声明式的调用,极大地提高了开发效率,使代码更清晰、更易于维护。


5. 服务容错:Hystrix 和 Sentinel 的区别?

在分布式环境中,避免服务出现雪崩效应是重中之重。这就是服务容错组件的作用。

Hystrix (已停止维护)

Hystrix 通过断路器 (Circuit Breaker) 模式来实现容错。

  • 熔断:当失败率达到阈值,断路器打开,所有请求直接失败,不再调用实际服务。
  • 降级:服务熔断或资源不足时,提供一种备选方案(fallback),返回一个托底数据。
@RestController
public class OrderController {

    @Autowired
    private OrderServiceClient orderServiceClient;

    // 使用 @HystrixCommand 指定降级方法
    @GetMapping("/user/{userId}/orders")
    @HystrixCommand(fallbackMethod = "getOrdersFallback")
    public List<Order> getOrders(@PathVariable Long userId) {
        return orderServiceClient.getOrdersByUserId(userId);
    }

    // 降级方法
    public List<Order> getOrdersFallback(Long userId) {
        return Collections.emptyList(); // 返回空列表作为托底数据
    }
}

Sentinel (阿里开源,目前主流)

Sentinel 功能更强大,不仅支持熔断降级,还支持流量控制、系统自适应保护、实时监控等。

对比表

特性HystrixSentinel
核心焦点断路器 (熔断器)流量控制、熔断降级、系统保护
配置方式代码注解为主控制台动态配置,规则可持久化
扩展性一般丰富 SPI 扩展接口
实时监控简单的监控界面功能强大的实时监控和控制台
规则持久化不支持支持多种数据源(如Nacos, Apollo)

结论

  • 新项目强烈推荐使用 Sentinel,功能更全面,控制台更友好,配置更灵活。
  • Hystrix 已停止维护,仅为遗留系统存在。

6. API 网关:Spring Cloud Gateway vs Zuul?

API 网关是所有微服务的流量入口,负责路由、过滤、鉴权、限流等。

Zuul 1.x (Netflix,基于阻塞IO,已淘汰)

Spring Cloud Gateway (官方推荐,基于响应式)

Spring Cloud Gateway 基于 WebFlux 响应式编程模型,性能更高,功能更强。

核心概念

  • Route (路由):定义匹配条件和转发目标。
  • Predicate (断言):匹配 HTTP 请求的条件(如路径、方法、头信息)。
  • Filter (过滤器):处理请求和响应的逻辑(如添加请求头、鉴权、限流)。

配置示例

spring:
  cloud:
    gateway:
      routes:
        - id: user_route # 路由ID
          uri: lb://user-service # 目标服务地址,lb:// 表示从注册中心负载均衡
          predicates:
            - Path=/api/user/** # 断言:路径匹配
          filters:
            - StripPrefix=1 # 过滤器:去掉路径中的第一个前缀(/api)
            - AddRequestHeader=X-Request-color, blue # 添加请求头

结论

  • 无条件选择 Spring Cloud Gateway,它是官方未来,性能优越,功能持续更新。Zuul 1.x 已彻底淘汰。

7. 分布式配置中心:Spring Cloud Config 和 Nacos?

集中管理所有微服务在不同环境下的配置文件。

Spring Cloud Config

  • Server端:从 Git、SVN 等仓库拉取配置。
  • Client端:从 Server 端获取配置。
  • 缺点:配置变更后,需要手动通过 Spring Cloud Bus 消息总线刷新所有客户端,流程繁琐。

Nacos Config

作为配置中心,Nacos 的优势巨大

  1. 开箱即用:与注册中心一体,无需额外部署。
  2. 动态刷新:通过 @RefreshScope 注解,客户端能自动监听配置变化并刷新,无需手动触发 Bus。
  3. 管理界面:提供友好的 Web UI 管理配置。
  4. 多环境与灰度:支持命名空间 (Namespace) 和数据ID (Data ID) 进行环境隔离和灰度发布。

使用示例

  1. 添加依赖spring-cloud-starter-alibaba-nacos-config

  2. bootstrap.yml 中配置 Nacos Server 地址

    spring:
      application:
        name: user-service
      cloud:
        nacos:
          config:
            server-addr: localhost:8848
            file-extension: yaml # 指定配置格式为yaml
            namespace: dev # 指定命名空间(用于环境隔离)
    
  3. 在 Controller 中使用 @Value 并开启自动刷新

    @RestController
    @RefreshScope // 这个注解是关键,允许动态刷新配置
    public class UserController {
    
        @Value("${user.config.title:默认标题}") // 冒号后面是默认值
        private String title;
    
        @GetMapping("/title")
        public String getTitle() {
            return this.title;
        }
    }
    

结论

  • Nacos 在配置中心方面完胜 Spring Cloud Config,是其完美的替代品,极大地简化了分布式配置的复杂度。

总结

组件类别过去式 (Netflix 体系)现在与未来 (主流选择)
服务发现EurekaNacos
负载均衡RibbonSpring Cloud LoadBalancer
服务调用FeignOpenFeign
服务容错HystrixSentinel
API网关Zuul 1.xSpring Cloud Gateway
配置中心Spring Cloud ConfigNacos

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值