背景
OpenFeign是微服务中服务远程调用组件。
circuitbreaker 是断路器的抽象接口。
resilience4j是断路器的一种实现。
在服务间远程调用过程中,为了避免服务雪崩,需要设置失败保护机制,当下游服务超时或者不可用时,上游服务可以快速返回,同时下游服务会降级,上游服务短时间不去请求下游服务。
实现远程调用
服务提供者
服务提供者就是正常的SpringBoot项目,为了让服务调用者可以请求该服务,需要将服务信息注册到Consul注册中心。
1依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</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-actuator</artifactId>
</dependency>
</dependencies>
2配置如下:
spring:
application:
name: system-application
cloud:
consul:
discovery:
service-name: ${spring.application.name}
instance-id: system-service
host: localhost
port: 8500
config:
format: yaml
data-key: system
enabled: true
watch:
enabled: true
wait-time: 5
config:
import: optional:consul:${spring.cloud.consul.host}:${spring.cloud.consul.port}/test
hello:
name
3还需要自己实现一个普通controller。
启动服务提供者,打开consul控制台,服务成功注册即可。
服务消费
1 添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<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-actuator</artifactId>
</dependency>
</dependencies>
相比服务提供者,多了一个断路器的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
2 配置:
spring:
application:
name: portal-application
cloud:
consul:
discovery:
service-name: ${spring.application.name}
instance-id: portal-service
host: localhost
port: 8500
config:
import: optional:consul:${spring.cloud.consul.host}:${spring.cloud.consul.port}
feign:
circuitbreaker:
enabled: true
# client:
# config:
# default:
# connectTimeout: 1000
# readTimeout: 1000
server:
port: 8081
配置文件中只添加如下配置,用于打开circuitbreaker。
feign:
circuitbreaker:
enabled: true
3 配置断路器, 这里配置了1ms的超时。
@Configuration
public class BreakerConfig {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(1)).build())
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.build());
}
}
4 实现FeignClient调用,主要是加入fallback逻辑,用于失败后的处理
@FeignClient(name ="system-application", fallback = UserClient.Fallback.class)
@Component
public interface UserClient {
@GetMapping("")
String getName();
@Component
static class Fallback implements UserClient {
@Override
public String getName() {
return "00000000000000000000000";
}
}
}
至此,基本的Demo已经完成。
启动服务消费者,访问feignClient的接口,发现返回了fallback类中配置的信息。证明断路器配置起作用。
除了断路器的配置外,如下的配置和断路器无关,支持配置了http请求的超时时间,如果超时,会报错,不会触发Fallback。
client:
config:
default:
connectTimeout: 1000
readTimeout: 1000
总结
- 加入断路器依赖
- feign.circuitbreaker.enabled: true 开启断路器
- 注入Resilience4JConfigBuilder
以上三步在服务调用方实现。