Resilience4j 保护 API 接口安全

2025-05-07
来源:

1. 简介

第三方接口调用在应用中十分常见,它使得不同系统和服务能够相互通信、共享数据和功能。然而,这种跨系统的交互也带来了一系列风险,特别是在接口稳定性、性能和安全性方面。因此,在调用第三方接口时,必须做好熔断降级策略,以确保系统的稳健性和可用性。

在第三方接口调用中,熔断降级的作用尤为重要。当第三方接口出现故障或响应缓慢时,如果没有熔断降级机制,调用方可能会长时间等待响应,甚至耗尽系统资源,导致整个应用崩溃。而通过熔断降级,调用方可以在检测到异常情况时迅速切断连接,避免进一步损失,并通过降级策略确保核心功能的稳定运行。

2. Resilience4j简介

Resilience4j是一个轻量级容错框架,设计灵感来源于Netflix 的Hystrix框架,为函数式编程所设计。

Resilience4j 提供了一组高阶函数(装饰器),包括断路器,限流器,重试,隔离,可以对任何的函数式接口,lambda表达式,或方法的引用进行增强,并且这些装饰器可以进行叠加。这样做的好处是,你可以根据需要选择特定的装饰器进行组合。

3. 实战案例

3.1 依赖管理





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

目标接口准备








@GetMapping("/info/{id}")publicObject info(@PathVariable("id") Integer id,     @RequestParam Map<String, Object> params) throws Exception {   // 模拟耗时3s   TimeUnit.SECONDS.sleep(3) ;   return Map.of("code", 0, "message", "success") ;}

3.2 RestTemplate接口调用

























@Servicepublic class CircuitService{
  private final RestTemplate restTemplate ;   // 这里注入的是Resilience4JCircuitBreakerFactory实例   private final CircuitBreakerFactory circuitBreakerFactory ;
  public CircuitService(RestTemplate restTemplate,       CircuitBreakerFactory circuitBreakerFactory) {    this.restTemplate = restTemplate ;    this.circuitBreakerFactory = circuitBreakerFactory ;   }
  public Object remoteService(Integer id) {    // 这里的akk的作用我们等会再说    CircuitBreaker create = this.circuitBreakerFactory         .create("akk") ;    return create.run(() -> this.restTemplate.getForObject("http://localhost:8088/demos/info/{id}", Map.class, id)           , ex -> Map.ofEntries(            entry("code", -1),            entry("message", ex.getMessage())        )) ;   }}

CircuitBreakerFactory#create 会创建 CircuitBreaker 的类的实例。运行方法需要一个 Supplier 和一个 Function。Supplier是要封装到断路器中的代码。Function是断路器跳闸时运行的后备函数。函数传递的是导致触发回退的Throwable。如果不想提供回退函数,可以选择将其排除在外。

请求结果


默认超时时间是1s,而上面我们的接口模拟了3s耗时,所以这里返回的是fallback降级后的输出。

3.3 WebClient接口调用

WebClient是非阻塞,响应式的远程接口调用,那么我们对应使用的断路器工厂是ReactiveResilience4JCircuitBreakerFactory我们只需要引入spring-boot-starter-webflux依赖即可。









private final WebClient webClient ; private final ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory ;
public CircuitBreakerService(WebClient webClient,    ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory) {   this.webClient = webClient ;   this.reactiveCircuitBreakerFactory = reactiveCircuitBreakerFactory ;}

接口调用








public Mono<Map> reactiveInvoke(Integer id) {   return webClient.get()      .uri("/demos/info/{id}", id)      .retrieve().bodyToMono(Map.class)      .transform(it -> this.reactiveCircuitBreakerFactory.create("akk").run(it,          ex -> Mono.just(Map.ofEntries(entry("code", -1), entry("message", ex.getMessage()))))) ;}

与上面RestTemplate错误差不多。

以上就是远程接口调用中如何应用Circuit Breaker,接下来将详细的讲解上面看到的CircutBreaker的创建。

3.4 基于注解

我们还可以通过注解+配置的方式,实现接口的熔断。











@CircuitBreaker(name = "a-info", fallbackMethod = "infoFallback")public Map<String, Object> info(Integer id) {   if (id == -1) {    throw new RuntimeException("非法数字") ;   }   return this.restTemplate.getForObject("http://localhost:8088/demos/info/{id}", Map.class, id) ;}public Map<String, Object> infoFallback(Integer id, Throwable e) {   return Map.of("code", -1, "message", e.getMessage(), "args", id) ;}

配置文件






resilience4j:   circuitbreaker:    instances:      a-info:        minimum-number-of-calls: 10

通过注解+配置的方式能加灵活的管理。

3.5 断路器创建

在上面的示例中我们没有对CircuitBreaker做任何的配置,直接通过CircuitBreakerFactory#create创建实例。接下来以Resilience4JCircuitBreakerFactory为例进行配置说明:

修改配置默认

我们可以对不同的实例进行不同的配置也可以统一使用默认的配置。在上面的案例中就是使用的默认的配置。而默认的配置,我们可以在配置文件中进行修改






resilience4j:   timelimiter:    configs:      default:        timeout-duration: 4s

超时时间设置为4s,而在上面我们的目标接口模拟耗时3s,这样配置后,我们再次请求接口

编程配置具体实例

除了上面的默认配置外,我们还可以对具体的实例进行配置















@Componentpublic class ReactiveCircuitBreakerCustomer implementsCustomizer<ReactiveResilience4JCircuitBreakerFactory> {
  @Override   public void customize(ReactiveResilience4JCircuitBreakerFactory tocustomize){    Consumer<Resilience4JConfigBuilder> customer = cb -> {      cb.circuitBreakerConfig(CircuitBreakerConfig.custom().build()) ;      cb.timeLimiterConfig(TimeLimiterConfig.custom()          .timeoutDuration(Duration.ofSeconds(4))          .build()) ;    };    tocustomize.configure(customer , "akk", "a2");   }}

通过上面的配置也能针对具体的实例id进行配置。


分享
下一篇:这是最后一篇
上一篇:这是第一篇
写评论...