【问题标题】:spring-cloud with RestTemplate//Ribbon/Eureka - retry when server not available带有 RestTemplate//Ribbon/Eureka 的 spring-cloud - 在服务器不可用时重试
【发布时间】:2015-02-12 15:26:03
【问题描述】:

我成功地让我的 RestTemplate 客户端使用 Eureka 发现远程服务,并使用功能区将调用转发给它,如文档中所述。 基本上,只需在我的 Application 类中添加以下注解,剩下的就交给 Spring-Boot 的魔法吧:

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableDiscoveryClient

(PS:您注意到我使用的是 spring-cloud:1.0.0-SNAPSHOT-BUILD 而不是 1.0.0.M3 - 但这似乎不会影响我的问题)。

当两个服务实例启动时,rest-template客户端成功地在两者之间负载均衡请求。但是,如果第一个实例在 Eureka 负载均衡器通知之前停止,客户端将不会回退到第二个实例,而是抛出异常。

因此我的问题是:有没有办法配置 RestTemplate/Ribbon/Eureka 堆栈,以在选择第一个位置的实例不可用时自动重试对另一个实例的调用? Zuul 代理和 feign 客户端“开箱即用”执行此操作,因此我相信该库拥有必要的功能......

有什么想法/提示吗?

谢谢, /伯特兰

【问题讨论】:

  • 或者是因为与 RestTemplate 的集成是使用拦截器完成的,其唯一目的是将 serviceId 转换为适当的 URL,但不会包装整个调用过程,因此无法执行任何“重试”逻辑?

标签: netflix spring-cloud


【解决方案1】:

RestTemplate 支持本身不知道如何进行任何重试(而 Spring Cloud 中的 Feign 客户端和代理支持则可以,正如您所注意到的)。我认为这可能是一件好事,因为它使您可以选择自己添加它。例如,使用Spring Retry,您可以使用简单的声明式风格:

@Retryable
public Object doSomething() {
   // use your RestTemplate here
}

(并将@EnableRetry 添加到您的@Configuration)。它与@HystrixCommand(来自 Spring Cloud / Javanica)完美结合:

@HystrixCommand
@Retryable
public Object doSomething() {
   // use your RestTemplate here
}

在这种形式中,即使重试成功,每次失败都计入断路器指标(也许我们可以改变它,或者保持这种状态是有意义的)。

【讨论】:

  • 好的,知道了。我试了一下@Retryable,它完美地完成了这项工作。但是,将@HystrixCommand 与回退方法一起使用似乎会产生干扰,因为它会在@Retryable 之前首先捕获异常。所以我有点困惑如何同时使用它们。
  • 我想可能是我很幸运——hystrix 和可重试的方面有相同的Order 所以是否捕获并重试异常取决于它们被 Spring 发现的顺序.作为记录,我的@Configuration@EnableCircuitBreaker @EnableRetry(proxyTargetClass=true)(按此顺序)。
  • 它们确实在此处以相反的顺序注册...但是好的,因此只需告诉 Spring 以适当的顺序注册它们即可。我会看看(除非你已经知道我该怎么做;-)
  • @BertrandRenuart:您解决了订购问题吗?如果,那么你能提供解决方案吗..
  • 是@Retryable 向其他服务器发送请求(NextServer 重试)?
【解决方案2】:

由于拦截器的顺序,无论@Configuration 类或@Retryable 方法上的注释顺序如何,我都无法让它与@HystrixCommand 和@Retryable 一起使用。我通过使用匹配的方法集创建另一个类来解决这个问题,并将 @HystrixCommand 注释的方法委托给第二个类中相应的 @Retryable 方法。您可能会让这两个类实现相同的接口。这有点让人头疼,但在可以配置订单之前,这就是我能想到的。仍在等待 Dave Syer 和 spring cloud 团队的真正解决方案。

public class HystrixWrapper {
    @Autowired
    private RetryableWrapper retryableWrapper;

    @HystrixCommand
    public Response doSomething(...) {
        return retryableWrapper.doSomething(...);
    }
}

public class RetryableWrapper {
    @Autowired
    private RestTemplate restTemplate;

    @Retryable
    public Response doSomething(...) {
        // do something with restTemplate;
    }
}

【讨论】:

  • EnableCircuitBreaker 和 EnableRetry 的排序是否已修复?
猜你喜欢
  • 2016-02-15
  • 2019-09-18
  • 2015-12-12
  • 2014-12-04
  • 2016-02-23
  • 2016-03-13
  • 2016-06-21
  • 1970-01-01
  • 2018-10-18
相关资源
最近更新 更多