Spring Cloud Circuit Breaker

class Spring Cloud Circuit Breaker

Spring Cloud Circuit Breaker 是 Spring Cloud 项目中的一个库,旨在为微服务架构提供熔断功能。熔断器模式是一种用于处理部分服务不可用的情况下提供稳定性的设计模式,通过监控服务的调用失败率来决定是否短暂地停止对该服务的调用。Spring Cloud Circuit Breaker 提供了一种抽象,使开发者能够以一致的方式使用不同的熔断器实现,例如 Resilience4j、Hystrix、Sentinel 等。

Spring Cloud Circuit Breaker 的主要功能

  1. 熔断器:监控服务调用的成功和失败,根据配置的策略进行熔断。
  2. 自动恢复:服务恢复后,自动重启调用,熔断器进入半开状态以检测服务是否恢复。
  3. 回退机制:在服务不可用时,提供回退方法以保证系统的稳定性。
  4. 监控和度量:提供丰富的指标和度量,帮助开发者了解系统的运行状态。

使用 Resilience4j 实现熔断器

Resilience4j 是一个轻量级的熔断器库,它提供了多种弹性处理机制,包括熔断器、限流器、重试、缓存和速率限制等。Spring Cloud Circuit Breaker 可以与 Resilience4j 集成,实现熔断器功能。

项目结构

我们将构建一个简单的 Spring Boot 应用,包含以下模块:

  • user-service:模拟一个提供用户信息的服务。
  • gateway-service:作为服务网关,通过 OpenFeign 调用 user-service,并使用 Spring Cloud Circuit Breaker 提供熔断器功能。

1. 创建 user-service

首先,我们创建一个简单的 user-service,它提供一个获取用户信息的 REST API。

添加依赖

pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

创建应用主类

package com.example.userservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

创建用户实体类

package com.example.userservice;

public class User {
    private Long id;
    private String name;
    private String email;

    // Getters and Setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

创建控制器

package com.example.userservice;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/users/{id}")
    public User getUserById(@PathVariable Long id) {
        if (id < 0) {
            throw new IllegalArgumentException("Invalid user ID");
        }

        User user = new User();
        user.setId(id);
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");
        return user;
    }
}
  • 用户控制器:提供了一个简单的 API 来获取用户信息,参数为用户 ID。

配置文件

src/main/resources/application.yml 中添加以下配置:

server:
  port: 8081

spring:
  application:
    name: user-service

2. 创建 gateway-service

创建一个 gateway-service,使用 Spring Cloud OpenFeign 调用 user-service,并使用 Resilience4j 作为熔断器。

添加依赖

pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

创建应用主类

package com.example.gatewayservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class GatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApplication.class, args);
    }
}

创建 Feign 客户端

package com.example.gatewayservice;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

// 定义 Feign 客户端接口
@FeignClient(name = "user-service", url = "http://localhost:8081")
public interface UserClient {

    @GetMapping("/users/{id}")
    User getUserById(@PathVariable("id") Long id);
}

创建用户实体类

package com.example.gatewayservice;

public class User {
    private Long id;
    private String name;
    private String email;

    // Getters and Setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

创建控制器

package com.example.gatewayservice;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;

@RestController
public class UserController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/gateway/users/{id}")
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserByIdFallback")
    public User getUserById(@PathVariable("id") Long id) {
        return userClient.getUserById(id);
    }

    // 熔断回退方法
    public User getUserByIdFallback(Long id, Throwable throwable) {
        User user = new User();
        user.setId(id);
        user.setName("Default User");
        user.setEmail("default@example.com");
        return user;
    }
}
  • 熔断器注解:在 getUserById 方法上添加 @CircuitBreaker 注解,指定熔断器的名称 userService,并设置回退方法 getUserByIdFallback

配置文件

src/main/resources/application.yml 中添加以下配置:

server:
  port: 8080

spring:
  application:
    name: gateway-service

feign:
  client:
    config:
      default:
        connect-timeout: 5000
        read-timeout: 5000
        loggerLevel: full

resilience4j:
  circuitbreaker:
    instances:
      userService:
        registerHealthIndicator: true
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10000
        permittedNumberOfCallsInHalfOpenState: 3
        minimumNumberOfCalls: 5
        slidingWindowType: COUNT_BASED
  • feign.client.config.default:配置 Feign 客户端的超时和日志级别。
  • resilience4j.circuitbreaker.instances.userService:配置 userService 熔断器实例的参数,包括滑动窗口大小、故障率阈值、打开状态等待时间等。

3. 启动项目

分别启动 user-servicegateway-service 项目:

  1. 启动 UserServiceApplication
  2. 启动 GatewayServiceApplication

4. 测试熔断器

使用 Curl 或 Postman 测试熔断器功能:

正常调用

请求用户 ID 为正数的用户信息:

curl http://localhost:8080/gateway/users/1

假设用户服务返回如下 JSON 响应:

{
  "id": 1,
  "name

": "John Doe",
  "email": "john.doe@example.com"
}

触发熔断

请求用户 ID 为负数的用户信息,模拟服务故障:

curl http://localhost:8080/gateway/users/-1

熔断器将调用回退方法,返回默认用户信息:

{
  "id": -1,
  "name": "Default User",
  "email": "default@example.com"
}

通过重复请求可以观察到,当故障率超过阈值时,熔断器将触发并直接调用回退方法,而不再尝试请求服务。

5. 监控和度量

Spring Boot Actuator 提供了对熔断器状态的监控支持,可以通过以下 URL 查看熔断器状态:

curl http://localhost:8080/actuator/health

输出将包含熔断器的健康状态:

{
  "status": "UP",
  "components": {
    "circuitBreakers": {
      "status": "UP",
      "details": {
        "userService": {
          "status": "CLOSED",
          "failureRate": "0.0%",
          "slowCallRate": "0.0%",
          "bufferedCalls": 0,
          "slowCalls": 0,
          "failureCalls": 0,
          "notPermittedCalls": 0
        }
      }
    }
  }
}

小结

Spring Cloud Circuit Breaker 提供了一种简单易用的方式来实现微服务中的熔断器功能。通过与 Resilience4j 的集成,我们可以灵活地配置熔断器的行为,并通过回退机制保证服务的稳定性。在实际应用中,可以根据具体需求调整熔断器的参数,以获得最佳的服务弹性和稳定性。

如果您有任何问题或需要进一步的帮助,请随时告诉我!

评论区
评论列表
menu