Hystrix Javanica 后备在 Spring Cloud 1.0 中不起作用

Posted

技术标签:

【中文标题】Hystrix Javanica 后备在 Spring Cloud 1.0 中不起作用【英文标题】:Hystrix Javanica fallback not working in Spring Cloud 1.0 【发布时间】:2015-06-13 22:33:08 【问题描述】:

我基于@spencergibb feign-eureka spring cloud starter example 构建了一个超级简单的 Hystrix 短路示例。起初我以为我无法触发 hystrix javanica 默认 fallbackMethod 由于 feign.. 现在,删除 feign,hystrix 默认 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 错误。当我卷曲这个客户端(到'/')时,非强制失败调用的事情正常进行。轮询也可以正常工作。当第二台服务器确实返回 500 错误时,不会调用 fallbackMethod 并且 curl 到 '/' 结束并返回错误。

根据 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();


【问题讨论】:

【参考方案1】:

@HystrixCommand 之所以有效,是因为 Spring 创建了一个代理来调用该方法。如果您从代理中调用该方法,它不会通过拦截器。您需要从另一个@Component 调用@HystrixCommand(或使用AspectJ)。

【讨论】:

是的,将makeMultipleCalls 移动到HelloClientApplication.hello 正是我的问题。现在它点击了为什么用 HystrixCommand 注释的方法需要在组件或服务中。和我澄清了很多。太糟糕了,Javanica 文档没有进一步澄清这一点,尽管它现在暗示了配置 Aspect 的选项。我将为未来的读者发布代码更新。

以上是关于Hystrix Javanica 后备在 Spring Cloud 1.0 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

hystrix进阶-注解hystrix-javanica使用

hystrix实战只javanica

javanica中的Hystrix异步方法不在spring-boot java应用程序中运行

如何对 javanica @HystrixCommand 注释方法进行单元测试?

Hystrix 后备禁用

Hystrix 后备实施是强制性的吗?