Hystrix Javanica 回退在 Spring Cloud 1.0 中不起作用
Hystrix Javanica fallback not working in Spring Cloud 1.0
我基于@spencergibb feign-eureka spring 云启动器示例构建了一个超级简单的 Hystrix 短路示例。起初我以为我无法让 hystrix javanica default fallbackMethod 触发由于 feign.. 现在,删除 feign,hystrix default fallbackMethod 仍然没有捕获异常。
pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>1.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
:
</dependencies>
主文件:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@RestController
public class HelloClientApplication {
@Autowired
HelloClientComponent helloClientComponent;
@RequestMapping("/")
public String hello() {
return helloClientComponent.makeMultipleCalls();
}
public static void main(String[] args) {
SpringApplication.run(HelloClientApplication.class, args);
}
}
HelloClientComponent.java(创建是因为我知道 javanica 希望在 spring 托管组件或服务中):
@Component
public class HelloClientComponent {
@Autowired
RestTemplate restTemplate;
public String makeMultipleCalls() {
int cnt=20;
StringBuilder sb = new StringBuilder();
while (cnt-- > 0) {
String response = theServerRequestRoot();
sb.append(response).append(" ");
}
return sb.toString();
}
public String theServersRequestRootFallback() {
System.out.println("BOMB!!!!!!");
return "BOMB!!!!!!";
}
@HystrixCommand(fallbackMethod = "theServersRequestRootFallback", commandKey = "callToServers")
public String theServerRequestRoot() {
ResponseEntity<String> result = restTemplate.getForEntity("http://HelloServer", String.class);
System.out.println(result.getBody());
return result.getBody();
}
}
我启动了 2 个服务器,一个总是成功并响应,另一个将在 30% 的时间内失败并出现 500 错误。当我卷曲这个客户端(到'/')时,非强制失败调用的事情正常进行。循环法也可以正常工作。当第二台服务器出现 return 500 错误时,不会调用 fallbackMethod 并且 curl 到 '/' 结束并且 return 出现错误。
根据 Spencer 和 Dave 的建议更新解决方案。更改为以下内容:
主要应用程序文件:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@RestController
public class HelloClientApplication {
@Autowired
HelloClientComponent helloClientComponent;
@RequestMapping("/")
public String hello() {
int cnt=20;
StringBuilder sb = new StringBuilder();
while (cnt-- > 0) {
String response = helloClientComponent.theServerRequestRoot(); // call directly to @Component in order for @HystrixCommand to intercept via AOP
sb.append(response).append(" ");
}
return sb.toString();
}
public static void main(String[] args) {
SpringApplication.run(HelloClientApplication.class, args);
}
}
HelloClientComponent.java:
@Component
public class HelloClientComponent {
@Autowired
RestTemplate restTemplate;
public String theServersRequestRootFallback() {
System.out.println("BOMB!!!!!!");
return "BOMB!!!!!!";
}
@HystrixCommand(fallbackMethod = "theServersRequestRootFallback", commandKey = "callToServers")
public String theServerRequestRoot() {
ResponseEntity<String> result = restTemplate.getForEntity("http://HelloServer", String.class);
System.out.println(result.getBody());
return result.getBody();
}
}
@HystrixCommand
之所以有效,是因为 Spring 创建了一个代理来调用该方法。如果您从代理内部调用该方法,它不会通过拦截器。您需要从另一个 @Component
(或使用 AspectJ)调用 @HystrixCommand
。
我基于@spencergibb feign-eureka spring 云启动器示例构建了一个超级简单的 Hystrix 短路示例。起初我以为我无法让 hystrix javanica default fallbackMethod 触发由于 feign.. 现在,删除 feign,hystrix default fallbackMethod 仍然没有捕获异常。
pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>1.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
:
</dependencies>
主文件:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@RestController
public class HelloClientApplication {
@Autowired
HelloClientComponent helloClientComponent;
@RequestMapping("/")
public String hello() {
return helloClientComponent.makeMultipleCalls();
}
public static void main(String[] args) {
SpringApplication.run(HelloClientApplication.class, args);
}
}
HelloClientComponent.java(创建是因为我知道 javanica 希望在 spring 托管组件或服务中):
@Component
public class HelloClientComponent {
@Autowired
RestTemplate restTemplate;
public String makeMultipleCalls() {
int cnt=20;
StringBuilder sb = new StringBuilder();
while (cnt-- > 0) {
String response = theServerRequestRoot();
sb.append(response).append(" ");
}
return sb.toString();
}
public String theServersRequestRootFallback() {
System.out.println("BOMB!!!!!!");
return "BOMB!!!!!!";
}
@HystrixCommand(fallbackMethod = "theServersRequestRootFallback", commandKey = "callToServers")
public String theServerRequestRoot() {
ResponseEntity<String> result = restTemplate.getForEntity("http://HelloServer", String.class);
System.out.println(result.getBody());
return result.getBody();
}
}
我启动了 2 个服务器,一个总是成功并响应,另一个将在 30% 的时间内失败并出现 500 错误。当我卷曲这个客户端(到'/')时,非强制失败调用的事情正常进行。循环法也可以正常工作。当第二台服务器出现 return 500 错误时,不会调用 fallbackMethod 并且 curl 到 '/' 结束并且 return 出现错误。
根据 Spencer 和 Dave 的建议更新解决方案。更改为以下内容:
主要应用程序文件:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@RestController
public class HelloClientApplication {
@Autowired
HelloClientComponent helloClientComponent;
@RequestMapping("/")
public String hello() {
int cnt=20;
StringBuilder sb = new StringBuilder();
while (cnt-- > 0) {
String response = helloClientComponent.theServerRequestRoot(); // call directly to @Component in order for @HystrixCommand to intercept via AOP
sb.append(response).append(" ");
}
return sb.toString();
}
public static void main(String[] args) {
SpringApplication.run(HelloClientApplication.class, args);
}
}
HelloClientComponent.java:
@Component
public class HelloClientComponent {
@Autowired
RestTemplate restTemplate;
public String theServersRequestRootFallback() {
System.out.println("BOMB!!!!!!");
return "BOMB!!!!!!";
}
@HystrixCommand(fallbackMethod = "theServersRequestRootFallback", commandKey = "callToServers")
public String theServerRequestRoot() {
ResponseEntity<String> result = restTemplate.getForEntity("http://HelloServer", String.class);
System.out.println(result.getBody());
return result.getBody();
}
}
@HystrixCommand
之所以有效,是因为 Spring 创建了一个代理来调用该方法。如果您从代理内部调用该方法,它不会通过拦截器。您需要从另一个 @Component
(或使用 AspectJ)调用 @HystrixCommand
。