我对这种断路技术很陌生。我试图用eureka服务器实现这项技术,但在这个后备方法点上遇到了困难。
我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.microservice</groupId>
<artifactId>inventory-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>inventory-client</name>
<description>Demo microservice project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
</properties>
<dependencies>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
我的应用程序属性
spring.application.name=inventory-client-app
server.port=8081
spring.cloud.circuitbreaker.resilience4j.enabled=false
resilience4j.circuitbreaker.instances.itemTypesBreaker.registerHealthIndicator=true
resilience4j.circuitbreaker.instances.itemTypesBreaker.slidingWindowSize=10
resilience4j.circuitbreaker.instances.itemTypesBreaker.permittedNumberOfCallsInHalfOpenState=3
resilience4j.circuitbreaker.instances.itemTypesBreaker.slidingWindowType=TIME_BASED
resilience4j.circuitbreaker.instances.itemTypesBreaker.minimumNumberOfCalls=20
resilience4j.circuitbreaker.instances.itemTypesBreaker.waitDurationInOpenState=50s
resilience4j.circuitbreaker.instances.itemTypesBreaker.failureRateThreshold=50
resilience4j.circuitbreaker.instances.itemTypesBreaker.eventConsumerBufferSize=10
我的控制器
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
@RestController
@RequestMapping("/inventory-client")
public class ItemTypeController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/item-types")
@ResponseStatus(HttpStatus.OK)
@CircuitBreaker(name="itemTypesBreaker",fallbackMethod = "itemTypesFallBack")
public List<ItemType> getAllItemTypes(){
List<ItemType> itemTypeList = (List<ItemType>) restTemplate.getForObject("http://inventory-catalog-app/inventory-catalog/item-types/", ItemType.class);
return itemTypeList;
}
private String itemTypesFallBack(Throwable t){
return "Item Catalog is down";
}
}
我不能用回退方法调用这个端点,我还缺少什么其他配置。提前谢谢。
我找到了一个解决方案。回退方法签名应该是这样的。
private List<ItemType> itemTypesFallBack(Throwable t){
System.out.println("Item Catalog is down");
return null;
}
在文档中,回退方法应该放在同一个类中,并且必须具有相同的方法签名,只有一个额外的目标异常参数。
如果您试图从NumberFormatException中恢复signature字符串回退(字符串参数,IllegalArgumentException异常(}将被调用。
通常我会创建带有RuntimeException额外参数的回退方法。在您的情况下,方法看起来像:
private List<ItemType> itemTypesFallBack(RuntimeException e){
...
}
我试图在eureka服务器上使用reslient4j实现重试,但在这个回退方法点上遇到了问题。我有与api相同的回退方法签名,但我还是得到了这个异常。
java.lang.NoSuchMethodException: class org.springframework.http.ResponseEntity class com.user.service.UserService.controllers.UserController.ratingHotelFallback(class java.lang.String,class java.lang.Throwable) at io.github.resilience4j.fallback.FallbackMethod.create(FallbackMethod.java:92) ~[resilience4j-spring-1.7.0.jar:1.7.0]
我的控制器
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
int retryCount = 1;
@GetMapping("/{userId}")
@Retry(name = "ratingHotelService", fallbackMethod = "ratingHotelFallback")
public ResponseEntity<User> getSingleUser(@PathVariable String userId){
System.out.println("Retry Count : " + retryCount);
retryCount++;
User user = userService.getUser(userId);
return ResponseEntity.ok(user);
}
public ResponseEntity<User> ratingHotelFallBack(String userId, Exception ex){
ex.printStackTrace();
User user = User.builder()
.userId("12345")
.name("dummy")
.email("dummy@gmail.com")
.about("This user is created dummy because some service is down")
.build();
return ResponseEntity.ok(user);
}
我的应用程序.yml
server:
port: 8081
error:
include-message: always
spring:
application:
name: USER-SERVICE
datasource:
url: jdbc:postgresql://localhost:5432/userdb
username: postgres
password: admin
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
eureka:
instance:
prefer-ip-address: true
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8080/eureka
management:
health:
circuitbreakers:
enabled: true
endpoints:
web:
exposure:
include: health
endpoint:
health:
show-details: always
resilience4j:
retry:
instances:
ratingHotelService:
max-attempts: 3
wait-duration: 2s
我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.user.service</groupId>
<artifactId>UserService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>UserService</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
我缺少配置了吗?谢谢