Клиент Spring Cloud Feign с тайм-аутом выключателя Hystrix по умолчанию составляет 2 секунды - PullRequest
2 голосов
/ 07 августа 2020

Воспроизводится в проекте на GitHub: spring-cloud-feign-hystrix-timeout-problem

Я использую Spring Boot 2.3.1.RELEASE с Spring Cloud Hoxton.SR6. А именно Feign client и Hystrix без Zuul и Eureka для получения ответов REST.

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-dependencies</artifactId>
   <version>Hoxton.SR6</version>
   <type>pom</type>
   <scope>import</scope>
</dependency>

Затем я использую следующие зависимости поверх Spring Boot 2.3.1.RELEASE и Spring Cloud Hoxton.SR6:

  • org.springframework.boot: spring-boot-starter
  • org.springframework.boot: spring-boot-starter-web
  • org.springframework.cloud: spring-cloud-starter-openfeign
  • org.springframework.cloud: spring-cloud-starter-netflix-hystrix

Я включаю @EnableFeignClients и @EnableCircuitBreaker и использую @FeignClient с простым откатом для регистрации и повторной генерации исключения:

@FeignClient(name="my-feign", url = "${feign.url}", fallbackFactory = MyFallbackFactory.class) {
public interface MyFeignClient {

    @PostMapping(value = "/api/dto")
    postDto(@RequestBody Dto dto);
}

со следующим application.yml таймаутом составляет около 1 секунда , потому что Hystrix по умолчанию имеет то же значение:

feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

11: 52: 05.493 INFO 10200 --- [nio-8060-exe c -2] com.mycompany.rest.MyController: вызов REST прямо сейчас!

11: 52: 06.538 ОШИБКА 24044 --- [nio-8060-exe c -1] oa c. c. C. [. [. [/]. [DispatcherServlet]: Servlet.service () для сервлета [dispatcherServlet] в контексте с путем [] сгенерировал исключение [Ошибка обработки запроса; вложенное исключение - com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient # postDto (Dto) истекло время ожидания и откат не удалось.] с root причиной

Что я пробовал?

Пока я добавляю следующие строки для увеличения тайм-аута до 60 секунд, тайм-аут становится примерно 2 секунды :

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 60000

11: 53: 33.590 ИНФОРМАЦИЯ 16052 --- [nio-8060-exe c -2] com.mycompany.rest.MyController: вызов REST прямо сейчас!

11: 53: 35.614 ОШИБКА 16052 --- [nio-8060-exe c -2] oa c. c. C. [. [. [/]. [DispatcherServlet]: Servlet .service () для сервлета [dispatcherServlet] в контексте с путем [] выдал исключение [Ошибка обработки запроса; вложенное исключение - com.netflix.hystrix.exception.HystrixRuntimeException: MyFeignClient # postDto (Dto) не удалось и откат не удалось.] с root причиной

Вызов переходит в резервный прямо в 2 секунд до тех пор, пока таймауты чтения / подключения Hystrix были увеличены. Однако я ожидаю достичь 5 секунд , если я объявил это в feign.client.config.default... тайм-аутах. Я чувствую, что мне не хватает другой конфигурации.

Q: Как увеличить время ожидания?

Изменить:

Ответы [ 2 ]

2 голосов
/ 11 августа 2020

Ваша конфигурация верна, и то, что вы описываете, является ожидаемым поведением. Проблема здесь в том, что исключение с Connection refused не генерируется после установленного вами тайм-аута - 10 секунд. Вместо этого он генерируется сразу после того, как реализация внутреннего сокета Java обнаруживает, что хост сервера недоступен. В простейшем случае вызываемый вами сервер не запущен и не работает.

Что касается того, почему происходит второе увеличение после того, как вы установили тайм-аут hystrix, вы можете отладить стек вызовов hystrix, чтобы узнать, что HystrixRuntimeException не генерируется в том же порядке.

До вашего пользовательского тайм-аута hystrix, у hystrix был тайм-аут по умолчанию, равный 1 секунде, что означает, что это исключение времени выполнения всегда генерируется раз в одну секунду с момента завершения выполнения, независимо от того, запрос выполнен или не выполнен. Так что в вашем случае Connection refused вполне может произойти после HystrixTimeoutException. После того, как вы установите тайм-аут больше, чем время ожидания для фиктивного клиента, HystrixTimeoutException создается только после того, как генерируется фиктивное исключение (из-за «Соединение отклонено»), отсюда и задержка.

// 'cause' should be different due to timing
public HystrixRuntimeException(... Exception cause, Throwable fallbackException)

Чтобы стимулировать тайм-аут, я бы сказал, вы можете принудительно установить тайм-аут на сервере, например, Thread.sleep(6000), чтобы остановить выполнение на стороне сервера, или просто установить точку останова в отладчике.

1 голос
/ 09 августа 2020

Вы можете попробовать определить свойство конфигурации тайм-аута Hystrix в одной строке (я знаю, что оно должно быть эквивалентно вложенному определению, которое вы предложили в своем файле YAML, но иногда я встречал свойства, которые были только загружается таким образом). Как вы можете увидеть в их тестах, именно так Spring Cloud настраивает таймаут Hystrix:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

Кроме того, хотя вы указали, что не используете Zuul или Eureka, пожалуйста, проверьте, используете ли вы Ribbon каким-либо образом, есть некоторые зависимости (см. https://github.com/Netflix/Hystrix/issues/1778 и https://github.com/spring-cloud/spring-cloud-netflix/issues/1324) между тайм-аутами Hystrix и Ribbon.

Если это так, вы должны настроить таймауты обеих библиотек:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
ribbon:
  ConnectTimeout: 5000
  ReadTimeout: 5000
...