2年前 (2022-11-16)  微服务 |   抢沙发  1521 
文章评分 0 次,平均分 0.0

在本文中,我们将介绍Spring Cloud断路器/熔断器,并学习如何利用它。

Spring Cloud断路器

直到最近,Spring Cloud只为我们提供了一种在应用程序中添加断路器的方法。这是通过使用Netflix Hystrix作为Spring Cloud Netflix项目的一部分实现的。

Spring Cloud Netflix项目实际上只是一个围绕Hystrix的基于注释的包装库。因此,这两个库是紧密耦合的。这意味着我们不能在不改变应用程序的情况下切换到另一个断路器实现。

Spring Cloud断路器项目解决了这一问题。它提供了跨不同断路器实现的抽象层。这是一个可插拔的架构。因此,我们可以根据提供的抽象/接口进行编码,并根据需要切换到另一个实现。

对于我们的示例,我们将只关注Resilience4J实现。然而,这些技术可以用于其他插件。

自动配置

为了在我们的应用程序中使用特定的断路器实现,我们需要添加适当的Spring启动器。在我们的例子中,让我们使用spring-cloud-starter-circuitbreaker-resilience4j

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
    <version>1.0.2.RELEASE</version>
</dependency>

如果自动配置机制在类路径中看到一个启动器,它将配置必要的断路器bean。

如果我们想禁用Resilience4J自动配置,可以设置spring.cloud.circuitbreaker.resilience4j.enabled属性设置为false

简单断路器示例

让我们使用Spring Boot创建一个web应用程序,以便探索Spring Cloud断路器库的工作原理。

我们将构建一个简单的web服务,返回相册列表。假设原始列表由第三方服务提供。为了简单起见,我们将使用Jsonplaceholder提供的外部虚拟API来检索列表:

https://jsonplaceholder.typicode.com/albums

创建断路器

让我们创建第一个断路器。我们将从注入CircuitBreakerFactory bean的实例开始:

@Service
public class AlbumService {
    
    @Autowired
    private CircuitBreakerFactory circuitBreakerFactory;

    //... 

}

现在,我们可以使用CircuitBreakerFactory#create方法轻松创建断路器。它将断路器标识符作为参数:

CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");

将任务包装在断路器中

为了包装和运行受断路器保护的任务,我们需要调用run方法,该方法以Supplier作为参数。

public String getAlbumList() {
    CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
    String url = "https://jsonplaceholder.typicode.com/albums";

    return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class));
}

断路器为我们运行我们的方法并提供容错。

有时,我们的外部服务可能需要太长时间才能响应,引发意外异常,或者外部服务或主机不存在。在这种情况下,我们可以提供回退作为run方法的第二个参数:

public String getAlbumList() {
    CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
    String url = "http://localhost:1234/not-real";
    
    return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class), 
      throwable -> getDefaultAlbumList());
}

回退的lambda接收Throwable作为输入,描述错误。这意味着我们可以根据触发回退的异常类型向调用者提供不同的回退结果。

在这种情况下,我们不会考虑例外情况。我们将返回一个缓存的相册列表。

如果外部调用以异常结束且未提供回退,Spring将抛出NoFallbackAvailableException

构建控制器

现在,让我们完成我们的示例并创建一个简单的控制器,它调用服务方法并通过浏览器显示结果:

@RestController
public class Controller {

    @Autowired
    private Service service;

    @GetMapping("/albums")
    public String albums() {
        return service.getAlbumList();
    }

}

最后,让我们调用REST服务并查看结果:

[GET] http://localhost:8080/albums

全局自定义配置

通常,默认配置是不够的。为此,我们需要根据我们的用例创建具有自定义配置的断路器。

为了覆盖默认配置,我们需要在@Configuration类中指定自己的bean和属性。

这里,我们将为所有断路器定义一个全局配置。为此,我们需要定义Customizer<CircuitBreakerFactory>bean。因此,让我们使用Resilience4JCircuitBreakerFactory实现。

首先,我们将根据Resilience4j教程定义断路器和限时器配置类:

CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
  .failureRateThreshold(50)
  .waitDurationInOpenState(Duration.ofMillis(1000))
  .slidingWindowSize(2)
  .build();
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
  .timeoutDuration(Duration.ofSeconds(4))
  .build();

接下来,让我们使用Resilience4JCcircuitBreakerFactory将配置嵌入定制bean中。configureDefault方法:

@Configuration
public class Resilience4JConfiguration {
    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> globalCustomConfiguration() {
        
        // the circuitBreakerConfig and timeLimiterConfig objects

        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
          .timeLimiterConfig(timeLimiterConfig)
          .circuitBreakerConfig(circuitBreakerConfig)
          .build());
    } 
}

特定自定义配置

当然,我们的应用中可以有多个断路器。因此,在某些情况下,我们需要每个断路器的特定配置。

类似地,我们可以定义一个或多个Customizer bean。然后,我们可以使用Resilience4JCcircuitBreakerFactory为每个配置提供不同的配置。配置方法:

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> specificCustomConfiguration1() {

    // the circuitBreakerConfig and timeLimiterConfig objects

    return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig)
      .timeLimiterConfig(timeLimiterConfig).build(), "circuitBreaker");
}

这里我们提供了第二个参数,即我们正在配置的断路器的id。

我们还可以通过向同一方法提供断路器ID列表来设置具有相同配置的多个断路器:

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> specificCustomConfiguration2() {

    // the circuitBreakerConfig and timeLimiterConfig objects

    return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig)
      .timeLimiterConfig(timeLimiterConfig).build(),
        "circuitBreaker1", "circuitBreaker2", "circuitBreaker3");
}

替代实施方案

我们已经看到了如何使用Resilience4j实现创建一个或多个带有Spring Cloud断路器的断路器。

然而,我们可以在应用程序中利用Spring Cloud断路器支持的其他实现:

  • Hystrix
  • Sentinel
  • Spring Retry

值得一提的是,我们可以在应用程序中混合和匹配不同的断路器实现。我们不仅仅局限于一个库。

以上库的功能比我们在这里探索的更多。然而,Spring Cloud断路器只是断路器部分的抽象。例如,除了本文中使用的断路器和限时器模块之外,Resilience4j还提供了其他模块,如RateLimiter、Bulkhead、Retry。

结论

在本文中,我们发现了Spring Cloud断路器项目。

首先,我们了解了什么是Spring Cloud断路器,以及它如何允许我们在应用程序中添加断路器。

接下来,我们利用Spring Boot自动配置机制来展示如何定义和集成断路器。此外,我们还演示了Spring Cloud断路器如何通过简单的REST服务工作。

最后,我们学会了一起配置所有断路器,也可以单独配置。

源码地址:https://github.com/eugenp/tutorials/tree/master/spring-cloud-modules/spring-cloud-circuit-breaker

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/2761.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册