Hystrix / Feign仅对HTTP状态做出反应429

时间:2018-03-04 12:15:16

标签: spring-cloud-netflix hystrix spring-cloud-feign http-status-code-429

我正在使用Feign中的spring-cloud-starter-feign将请求发送到已定义的后端。我想使用Hystrix作为断路器,但仅针对一种用例:如果后端以HTTP 429: Too many requests代码响应,我的Feign客户端应该等待一小时,直到它接触到再次真正的后端。在此之前,应该执行回退方法。

我如何配置我的Spring Boot(1.5.10)应用程序才能实现这一目标?我看到很多配置可能性,但只有少数例子 - 在我看来 - 很遗憾没有解决用例。

2 个答案:

答案 0 :(得分:1)

这可以通过定义ErrorDecoder并手动控制Hystrix断路器来实现。您可以检查异常中的响应代码并提供自己的后备。此外,如果您希望重试请求,请将您的异常包装并抛出RetryException

要满足您的重试要求,还要使用适当的配置注册Retryer bean。请记住,使用Retryer会占用一段时间的线程。 Retryer的默认实现也使用指数退避策略。

以下是从OpenFeign文档中获取的ErrorDecoder示例:

public class StashErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() >= 400 && response.status() <= 499) {
            return new StashClientException(
                response.status(),
                response.reason()
            );
        }
        if (response.status() >= 500 && response.status() <= 599) {
            return new StashServerException(
                response.status(),
                response.reason()
            );
        }
        return errorStatus(methodKey, response);
    } 
}

在您的情况下,您会根据需要对419做出反应。

您可以强制打开在运行时设置此属性的断路器

hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen

ConfigurationManager.getConfigInstance()
    .setProperty(
    "hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen", true);

用您自己的命令替换HystrixCommandKey。您需要在所需时间后将此断路器恢复到关闭状态。

答案 1 :(得分:0)

我可以通过以下调整来解决它:

application.yml中的属性:

hystrix.command.commandKey:
  execution.isolation.thread.timeoutInMilliseconds: 10_000
  metrics.rollingStats.timeInMilliseconds: 10_000
  circuitBreaker:
    errorThresholdPercentage: 1
    requestVolumeThreshold: 1
    sleepWindowInMilliseconds: 3_600_000

相应Java类中的代码:

@HystrixCommand(fallbackMethod = "fallbackMethod", commandKey = COMMAND_KEY)
public void doCall(String parameter) {
    try {
        feignClient.doCall(parameter);
    } catch (FeignException e) {
        if (e.status() == 429) {
            throw new TooManyRequestsException(e.getMessage());
        } 
    }
}