Spring Retry в лямбда-функции не работает - PullRequest
0 голосов
/ 15 марта 2019

У меня есть лямбда-функция, созданная с помощью Spring Boot, которая выполняет REST-вызов службы, которая может принимать 10 запросов в секунду. После этих 10 запросов я получаю 403.

Попытка заставить метод работать в рамках этого ограничения оказалась трудной.

На данный момент мой код выглядит как

@Slf4j
@UtilityClass
public class HttpUtil {

    private final RestTemplate restTemplate = new RestTemplate();

    @Retryable(maxAttempts = 60, backoff = @Backoff(delay = 10000, multiplier = 2))
    public ResponseEntity<String> sendPostRequest(@NonNull final MultiValueMap<String, Object> data, @NonNull final String url) {
        final HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(data, new HttpHeaders());

        return restTemplate.postForEntity(url, request, String.class);
    }
}

Однако, если я отключу это и проверим журналы, я вижу, что исключение 403 генерируется снова и снова, и, кажется, не происходит никакого периода "отступления".

Я попытался расширить RetryListenerSupport, чтобы добавить больше журналов, чтобы я мог видеть фактический период отключения, но, похоже, он был проигнорирован, несмотря на загрузку. Нужно ли это использовать с RetryTemplate`, а не только с аннотацией?

Иначе, очевидно, что-то не так с моей аннотацией? или есть намного более простой способ достичь "10 запросов в секунду" на моем методе?

редактировать:

Класс конфигурации

@EnableRetry
@Configuration
public class RetryTemplateConfig {

    @Bean
    public RetryTemplate retryTemplate() {
        final RetryTemplate retryTemplate = new RetryTemplate();
        retryTemplate.registerListener(new DefaultListenerSupport());
        return retryTemplate;
    }
}

И очень простой слушатель

@Slf4j
public class DefaultListenerSupport extends RetryListenerSupport {

    @Override
    public <T, E extends Throwable> void close(final RetryContext context,
                                               final RetryCallback<T, E> callback, final Throwable throwable) {

        log.info("onClose {}", throwable.getMessage());

        super.close(context, callback, throwable);
    }

    @Override
    public <T, E extends Throwable> void onError(final RetryContext context,
                                                 final RetryCallback<T, E> callback, final Throwable throwable) {

        log.info("onError {}", throwable.getMessage());

        super.onError(context, callback, throwable);
    }

    @Override
    public <T, E extends Throwable> boolean open(final RetryContext context,
                                                 final RetryCallback<T, E> callback) {

        log.info("onOpen");

        return super.open(context, callback);
    }
}

Приветствия

1 Ответ

1 голос
/ 15 марта 2019

Класс, использующий аннотацию @Retryable, должен быть bean-компонентом Spring, в противном случае вам нужно будет использовать RetryTemplate напрямую вместо аннотации.

Если вы не хотите, чтобы ваш класс был бобом, вы можете сделать:

private static final RetryTemplate retryTemplate = new RetryTemplate();
    static {
         SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
         retryPolicy.setMaxAttempts(60);
         ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
         backOffPolicy.setMultiplier(2);
         backOffPolicy.setInitialInterval(10000);
         retryTemplate.setRetryPolicy(retryPolicy);
         retryTemplate.setBackOffPolicy(backOffPolicy);
    }
    private void doSomething() {
        retryTemplate.execute(retryContext -> {
            return restTemplate.postForEntity(url, request, String.class);
        });
    }
...