## 一、网关的作用 **Gateway 网关是微服务架构中的唯一入口**。它扮演着一个**反向代理**和**门面**的角色,所有外部客户端(如Web前端、移动App)的请求首先都会经过网关,再由网关路由到后端的各个微服务。 在没有网关的微服务架构中,客户端需要直接与多个微服务通信,这会带来诸多问题: 1. **客户端复杂度高**:客户端需要知道所有微服务的网络位置(IP/域名),并自行实现负载均衡、处理不同服务的故障。这对前端应用来说非常繁琐且难以维护。 2. **交叉关注点重复**:每个微服务都需要实现一些通用功能,如身份认证、授权、日志记录、限流等。这违反了“Don‘t Repeat Yourself (DRY)”原则,增加了开发和维护成本。 3. **暴露内部细节**:直接将微服务暴露给外界,可能会暴露内部架构,存在安全风险。 4. **协议不匹配**:后端微服务可能使用高性能但对客户端不友好的协议(如gRPC、AMQP),而客户端通常使用HTTP/1.1或WebSocket。 Gateway 网关的核心作用就是将这些公共关注点抽象出来,集中处理,为客户端提供一个统一、简洁、安全的入口。  ## 二、创建Gateway子模块 #### 1、添加依赖 ```xml org.springframework.cloud spring-cloud-starter-gateway-server-webflux org.springframework.cloud spring-cloud-starter-netflix-eureka-client ``` #### 2、创建主启动类 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } } ``` #### 3、创建配置 在资源目录下创建`application.yml` ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** #- id: consumer2 #这里改写成服务名 # uri: lb://consumer2 #这里改写成服务名 # predicates: # - Path=/test/id/** #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} ``` ## 三、测试 可以访问[localhost:14000/test/id/112312](http://localhost:14000/test/id/112312)来进行测试  ## 四、过滤器 #### 1、局部过滤器 实现`GatewayFilter`接口或继承`AbstractGatewayFilterFactory`类实现,是针对单个路由的过滤器,通常使用后者 ##### 创建过滤器 创建`filter/CustomFilter.java` ```java import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class CustomFilter extends AbstractGatewayFilterFactory { public CustomFilter() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { // 前置处理 if (config.isEnableLog()) { System.out.println("请求路径: " + exchange.getRequest().getPath()); System.out.println("自定义参数: " + config.getCustomParam()); } // 修改请求 ServerHttpRequest modifiedRequest = exchange.getRequest().mutate() .header("X-Custom-Filter", config.getCustomParam()) .build(); ServerWebExchange modifiedExchange = exchange.mutate() .request(modifiedRequest) .build(); // 执行过滤器链 return chain.filter(modifiedExchange) .then(Mono.fromRunnable(() -> { // 后置处理 if (config.isEnableLog()) { System.out.println("请求处理完成"); } })); }; } // 定义过滤器的名称,需要在配置文件中填写 @Override public String name() { return "CustomFilter"; } // 配置类,用于接收配置文件中的参数 public static class Config { private boolean enableLog = true; private String customParam = "default-value"; // getter 和 setter 方法 public boolean isEnableLog() { return enableLog; } public void setEnableLog(boolean enableLog) { this.enableLog = enableLog; } public String getCustomParam() { return customParam; } public void setCustomParam(String customParam) { this.customParam = customParam; } } } ``` ##### 添加过滤器 修改`application.yml`配置文件 ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** filters: - name: CustomFilter # 过滤器名称 args: enableLog: true customParam: "my-custom-value" #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} ``` 访问[localhost:14000/test/id/112312](http://localhost:14000/test/id/112312)可以看到  #### 2、全局过滤器 实现`GlobalFilter`接口,作用于所有路由,不需要单独配置。可以通过全局过滤器实现一些共通功能,并且全局过滤器也是使用比较多的过滤器。 ##### 创建过滤器 创建`filter/GlobalAuthFilter.java` ```java import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; //使用@Component注解将过滤器放入Spring容器中。 @Component public class GlobalAuthFilter implements GlobalFilter { /** * 执行过滤器中的业务逻辑。 * ServerWebExchange:相当于请求响应的上下文。 * GatewayFilterChain:网关过滤的链表,用于过滤器的链式调用。 */ @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { //获取请求参数 String token = exchange.getRequest().getQueryParams().getFirst("token"); if (token == null) { //响应HTTP状态码(401:没有访问权限) exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); //请求结束 return exchange.getResponse().setComplete(); } //继续执行过滤器链中的下一个资源 return chain.filter(exchange); } } ``` 重新启动后访问[localhost](http://localhost:14000/test/id/112312)会发现出现了401  需要加上`?token=`参数来访问[localhost:14000/test/id/112312?token=2](http://localhost:14000/test/id/112312?token=2) #### 3、优先级 从后台输出可以发现,局部过滤器的优先级是高于全局的过滤器的。  请求会先经过局部过滤器,后在内部发送给全局过滤器,再由全局过滤器向微服务发送请求。 ## 五、网关熔断 不论是服务消费者调用服务提供者时、还是通过网关调用微服务时,都需要进行熔断处理。 #### 1、添加依赖 ```xml org.springframework.cloud spring-cloud-starter-circuitbreaker-reactor-resilience4j ``` #### 2、配置熔断器 修改`网关`的`Application.yml` ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** filters: - name: CustomFilter # 过滤器名称 args: enableLog: true customParam: "my-custom-value" # 熔断器 - name: CircuitBreaker args: name: userServiceBreaker fallbackUri: forward:/fallback/user # 请求限流 需要配置Redis数据库 #- name: RequestRateLimiter # args: # redis-rate-limiter.replenishRate: 10 # 每秒允许的请求数 # redis-rate-limiter.burstCapacity: 20 # 最大突发请求数 #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} resilience4j: circuitbreaker: instances: userServiceBreaker: registerHealthIndicator: true failureRateThreshold: 50 # 失败率阈值,超过50%触发熔断 minimumNumberOfCalls: 5 # 最小调用次数 automaticTransitionFromOpenToHalfOpenEnabled: true waitDurationInOpenState: 10s # 熔断开启状态的等待时间 permittedNumberOfCallsInHalfOpenState: 3 slidingWindowSize: 10 slidingWindowType: COUNT_BASED timelimiter: # 超时配置(可选) instances: userServiceBreaker: timeoutDuration: 2s ``` #### 3、创建Fallback控制器 ```java import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController @RequestMapping("/fallback") public class FallbackController { @GetMapping("/user") public Mono> userFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body("用户服务暂时不可用,请稍后重试")); } @GetMapping("/product") public Mono> productFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body(new ErrorResponse("PRODUCT_SERVICE_UNAVAILABLE", "商品服务暂时不可用"))); } // 通用fallback @GetMapping("/default") public Mono> defaultFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body("服务暂时不可用,请稍后重试")); } // 错误响应DTO public static class ErrorResponse { private String code; private String message; private long timestamp; public ErrorResponse(String code, String message) { this.code = code; this.message = message; this.timestamp = System.currentTimeMillis(); } // getter和setter public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public long getTimestamp() { return timestamp; } public void setTimestamp(long timestamp) { this.timestamp = timestamp; } } } ``` #### 4、自定义熔断配置类(可选) ```java import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.timelimiter.TimeLimiterConfig; import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JCircuitBreakerFactory; import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder; import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.Duration; @Configuration public class CircuitBreakerConfiguration { @Bean public Customizer defaultCustomizer() { return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(50) // 失败率阈值 .slowCallRateThreshold(50) // 慢调用率阈值 .slowCallDurationThreshold(Duration.ofSeconds(2)) // 慢调用定义 .waitDurationInOpenState(Duration.ofSeconds(60)) // 熔断开启到半开的等待时间 .permittedNumberOfCallsInHalfOpenState(3) // 半开状态允许的调用次数 .minimumNumberOfCalls(10) // 最小调用次数 .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) // 滑动窗口类型 .slidingWindowSize(10) // 滑动窗口大小 .recordExceptions(Exception.class) // 记录哪些异常 .build()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(5)) // 超时时间 .build()) .build()); } // 为特定服务配置自定义熔断器 @Bean public Customizer userServiceCustomizer() { return factory -> factory.configure(builder -> builder .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(30) .waitDurationInOpenState(Duration.ofSeconds(30)) .build()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(3)) .build()), "userServiceBreaker"); } } ``` Loading... ## 一、网关的作用 **Gateway 网关是微服务架构中的唯一入口**。它扮演着一个**反向代理**和**门面**的角色,所有外部客户端(如Web前端、移动App)的请求首先都会经过网关,再由网关路由到后端的各个微服务。 在没有网关的微服务架构中,客户端需要直接与多个微服务通信,这会带来诸多问题: 1. **客户端复杂度高**:客户端需要知道所有微服务的网络位置(IP/域名),并自行实现负载均衡、处理不同服务的故障。这对前端应用来说非常繁琐且难以维护。 2. **交叉关注点重复**:每个微服务都需要实现一些通用功能,如身份认证、授权、日志记录、限流等。这违反了“Don‘t Repeat Yourself (DRY)”原则,增加了开发和维护成本。 3. **暴露内部细节**:直接将微服务暴露给外界,可能会暴露内部架构,存在安全风险。 4. **协议不匹配**:后端微服务可能使用高性能但对客户端不友好的协议(如gRPC、AMQP),而客户端通常使用HTTP/1.1或WebSocket。 Gateway 网关的核心作用就是将这些公共关注点抽象出来,集中处理,为客户端提供一个统一、简洁、安全的入口。  ## 二、创建Gateway子模块 #### 1、添加依赖 ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ``` #### 2、创建主启动类 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } } ``` #### 3、创建配置 在资源目录下创建`application.yml` ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** #- id: consumer2 #这里改写成服务名 # uri: lb://consumer2 #这里改写成服务名 # predicates: # - Path=/test/id/** #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} ``` ## 三、测试 可以访问[localhost:14000/test/id/112312](http://localhost:14000/test/id/112312)来进行测试  ## 四、过滤器 #### 1、局部过滤器 实现`GatewayFilter`接口或继承`AbstractGatewayFilterFactory`类实现,是针对单个路由的过滤器,通常使用后者 ##### 创建过滤器 创建`filter/CustomFilter.java` ```java import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> { public CustomFilter() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { // 前置处理 if (config.isEnableLog()) { System.out.println("请求路径: " + exchange.getRequest().getPath()); System.out.println("自定义参数: " + config.getCustomParam()); } // 修改请求 ServerHttpRequest modifiedRequest = exchange.getRequest().mutate() .header("X-Custom-Filter", config.getCustomParam()) .build(); ServerWebExchange modifiedExchange = exchange.mutate() .request(modifiedRequest) .build(); // 执行过滤器链 return chain.filter(modifiedExchange) .then(Mono.fromRunnable(() -> { // 后置处理 if (config.isEnableLog()) { System.out.println("请求处理完成"); } })); }; } // 定义过滤器的名称,需要在配置文件中填写 @Override public String name() { return "CustomFilter"; } // 配置类,用于接收配置文件中的参数 public static class Config { private boolean enableLog = true; private String customParam = "default-value"; // getter 和 setter 方法 public boolean isEnableLog() { return enableLog; } public void setEnableLog(boolean enableLog) { this.enableLog = enableLog; } public String getCustomParam() { return customParam; } public void setCustomParam(String customParam) { this.customParam = customParam; } } } ``` ##### 添加过滤器 修改`application.yml`配置文件 ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** filters: - name: CustomFilter # 过滤器名称 args: enableLog: true customParam: "my-custom-value" #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} ``` 访问[localhost:14000/test/id/112312](http://localhost:14000/test/id/112312)可以看到  #### 2、全局过滤器 实现`GlobalFilter`接口,作用于所有路由,不需要单独配置。可以通过全局过滤器实现一些共通功能,并且全局过滤器也是使用比较多的过滤器。 ##### 创建过滤器 创建`filter/GlobalAuthFilter.java` ```java import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; //使用@Component注解将过滤器放入Spring容器中。 @Component public class GlobalAuthFilter implements GlobalFilter { /** * 执行过滤器中的业务逻辑。 * ServerWebExchange:相当于请求响应的上下文。 * GatewayFilterChain:网关过滤的链表,用于过滤器的链式调用。 */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //获取请求参数 String token = exchange.getRequest().getQueryParams().getFirst("token"); if (token == null) { //响应HTTP状态码(401:没有访问权限) exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); //请求结束 return exchange.getResponse().setComplete(); } //继续执行过滤器链中的下一个资源 return chain.filter(exchange); } } ``` 重新启动后访问[localhost](http://localhost:14000/test/id/112312)会发现出现了401  需要加上`?token=`参数来访问[localhost:14000/test/id/112312?token=2](http://localhost:14000/test/id/112312?token=2) #### 3、优先级 从后台输出可以发现,局部过滤器的优先级是高于全局的过滤器的。  请求会先经过局部过滤器,后在内部发送给全局过滤器,再由全局过滤器向微服务发送请求。 ## 五、网关熔断 不论是服务消费者调用服务提供者时、还是通过网关调用微服务时,都需要进行熔断处理。 #### 1、添加依赖 ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> </dependency> ``` #### 2、配置熔断器 修改`网关`的`Application.yml` ```yml server: port: 14000 spring: application: name: gateway #下面是关于Spring Cloud Gateway的配置 cloud: gateway: server: webflux: routes: - id: consumer #这里改写成服务名 uri: lb://consumer #这里改写成服务名 predicates: - Path=/test/id/** filters: - name: CustomFilter # 过滤器名称 args: enableLog: true customParam: "my-custom-value" # 熔断器 - name: CircuitBreaker args: name: userServiceBreaker fallbackUri: forward:/fallback/user # 请求限流 需要配置Redis数据库 #- name: RequestRateLimiter # args: # redis-rate-limiter.replenishRate: 10 # 每秒允许的请求数 # redis-rate-limiter.burstCapacity: 20 # 最大突发请求数 #eureka配置(Gateway也要称为Eureka的一个客户端) eureka: client: service-url: defaultZone: http://eurekaServer13000:13000/eureka,http://eurekaServer13001:13001/eureka instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} resilience4j: circuitbreaker: instances: userServiceBreaker: registerHealthIndicator: true failureRateThreshold: 50 # 失败率阈值,超过50%触发熔断 minimumNumberOfCalls: 5 # 最小调用次数 automaticTransitionFromOpenToHalfOpenEnabled: true waitDurationInOpenState: 10s # 熔断开启状态的等待时间 permittedNumberOfCallsInHalfOpenState: 3 slidingWindowSize: 10 slidingWindowType: COUNT_BASED timelimiter: # 超时配置(可选) instances: userServiceBreaker: timeoutDuration: 2s ``` #### 3、创建Fallback控制器 ```java import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController @RequestMapping("/fallback") public class FallbackController { @GetMapping("/user") public Mono<ResponseEntity<String>> userFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body("用户服务暂时不可用,请稍后重试")); } @GetMapping("/product") public Mono<ResponseEntity<Object>> productFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body(new ErrorResponse("PRODUCT_SERVICE_UNAVAILABLE", "商品服务暂时不可用"))); } // 通用fallback @GetMapping("/default") public Mono<ResponseEntity<String>> defaultFallback() { return Mono.just(ResponseEntity .status(HttpStatus.SERVICE_UNAVAILABLE) .body("服务暂时不可用,请稍后重试")); } // 错误响应DTO public static class ErrorResponse { private String code; private String message; private long timestamp; public ErrorResponse(String code, String message) { this.code = code; this.message = message; this.timestamp = System.currentTimeMillis(); } // getter和setter public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public long getTimestamp() { return timestamp; } public void setTimestamp(long timestamp) { this.timestamp = timestamp; } } } ``` #### 4、自定义熔断配置类(可选) ```java import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.timelimiter.TimeLimiterConfig; import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JCircuitBreakerFactory; import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder; import org.springframework.cloud.client.circuitbreaker.Customizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.Duration; @Configuration public class CircuitBreakerConfiguration { @Bean public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() { return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(50) // 失败率阈值 .slowCallRateThreshold(50) // 慢调用率阈值 .slowCallDurationThreshold(Duration.ofSeconds(2)) // 慢调用定义 .waitDurationInOpenState(Duration.ofSeconds(60)) // 熔断开启到半开的等待时间 .permittedNumberOfCallsInHalfOpenState(3) // 半开状态允许的调用次数 .minimumNumberOfCalls(10) // 最小调用次数 .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) // 滑动窗口类型 .slidingWindowSize(10) // 滑动窗口大小 .recordExceptions(Exception.class) // 记录哪些异常 .build()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(5)) // 超时时间 .build()) .build()); } // 为特定服务配置自定义熔断器 @Bean public Customizer<Resilience4JCircuitBreakerFactory> userServiceCustomizer() { return factory -> factory.configure(builder -> builder .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(30) .waitDurationInOpenState(Duration.ofSeconds(30)) .build()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(3)) .build()), "userServiceBreaker"); } } ``` 最后修改:2025 年 12 月 09 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 👆请简单粗暴地爱我。