Вопрос: Использование автоматического выключателя в устойчивости SAP Cloud SDK - PullRequest
1 голос
/ 19 апреля 2020

Когда я попытался использовать ResilienceDecorator.executeCallable () для включения автоматического выключателя, мне пришлось выбросить ResilienceRuntimeException в моем вызове, чтобы заставить работать прерывание цепи. Пример кода, как показано ниже. Без него автоматический выключатель всегда замкнут. это правильный способ сделать это?

response = ResilienceDecorator.executeCallable(() -> {
    HttpResponse response1 = tryHttpClient.get().execute(request);
    if (response1.getStatusLine().getStatusCode() == 404){
      throw new ResilienceRuntimeException("404 error is raised when calling SB api");
    }
    return response1;
  },
          ResilienceConfiguration.of(SubscriptionBillingAdapter.class).isolationMode(ResilienceIsolationMode.TENANT_OPTIONAL).timeLimiterConfiguration(ResilienceConfiguration.TimeLimiterConfiguration.of().timeoutDuration(Duration.ofSeconds(6L))).circuitBreakerConfiguration(ResilienceConfiguration.CircuitBreakerConfiguration.of().waitDuration(Duration.ofSeconds(600000L)).failureRateThreshold(1).closedBufferSize(1).halfOpenBufferSize(1)),
          e -> {LOG.warn("resiliience fallback call: " + e); return response1;});

Я спрашиваю, так как не вижу никакого документа об этом. Кроме того, когда я проверял, как получается конфигурация назначения в SCP, я увидел следующий код в com.sap.cloud.sdk.cloudplatform.connectivity.DestinationService. Не выдает ResilienceRuntimeException при использовании ResilienceDecorator.executeCallable (). поэтому мой вопрос: нужно ли выкидывать ResilienceRuntimeException или нет, чтобы выключатель работал? если мне не нужно, что-то не так в моем коде?

return (String)ResilienceDecorator.executeCallable(() -> {
            XsuaaCredentials xsuaaCredentials = (new ServiceCredentialsRetriever()).getClientCredentials("destination");
            AccessToken accessToken;
            if (propagateUser) {
                accessToken = xsuaaService.retrieveAccessTokenViaUserTokenExchange(xsuaaCredentials.getXsuaaUri(), xsuaaCredentials.getCredentials(), useProviderTenant);
            } else {
                accessToken = xsuaaService.retrieveAccessTokenViaClientCredentialsGrant(xsuaaCredentials.getXsuaaUri(), xsuaaCredentials.getCredentials(), useProviderTenant);
            }

            return this.fetchDestinationsJson(servicePath, accessToken);
        }, ResilienceConfiguration.of(DestinationService.class).isolationMode(ResilienceIsolationMode.TENANT_OPTIONAL).timeLimiterConfiguration(TimeLimiterConfiguration.of().timeoutDuration(Duration.ofSeconds(6L))).circuitBreakerConfiguration(CircuitBreakerConfiguration.of().waitDuration(Duration.ofSeconds(6L))));

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Нет, вам не нужно бросать ResilienceRuntimeException. На самом деле SDK использует это только для того, чтобы обернуть отмеченные и непроверенные исключения в непроверенное исключение, которое объединяет все виды сбоев, возникающих при отказоустойчивом вызове.

Пожалуйста, расширите свой вопрос более подробной информацией, затем я расширю это ответ:

  • Какую версию SDK вы используете?
  • Как (и как часто) вы вызываете оформленный вызываемый элемент? Пожалуйста, расширьте блок кода.
  • Пожалуйста, укажите точное поведение, которое вы наблюдаете. Какое исключение выдается, когда вы вызываете украшенный призыв? Если размыкатель цепи размыкается, это должно быть CallNotPermittedException, заключенное в ResilienceRuntimeException
  • Уменьшите вызываемое значение, чтобы просто вызвать исключение, чтобы упростить код
  • Уменьшите конфигурацию устойчивости только используйте автоматический выключатель (рычаг ResilienceConfiguration.empty()). Если это сработает, добавьте материал обратно, пока он этого не сделает.

Для справки также найдите документацию resilience4j , которую SDK использует под капотом для выполнения упругих операций.

0 голосов
/ 21 апреля 2020

Стивен

Я не самый опытный в этой части c, но, глядя на ваш код, кажется мне подходящим . Когда сервер возвращает 404 Not found, это не указывает на сбой или ошибку службы, но этот ресурс просто не найден. Если в вашем случае 404 означает, что произошла ошибка и запрос должен быть повторен с resilient approach, вы должны выбросить это исключение , чтобы сообщить Resilience4J, что что-то пошло не так.

Пока мы работаем над улучшением нашей документации, я рекомендую вам взглянуть на существующее руководство , объясняющее устойчивость в контексте SAP Cloud SDK . Там мы также добавляем ResilienceRuntimeException для ясности:

public List<BusinessPartner> execute() {
        return ResilienceDecorator.executeSupplier(this::run, myResilienceConfig, e -> {
            logger.warn("Fallback called because of exception.", e);
            return Collections.emptyList();
        });
    }

private List<BusinessPartner> run() {
        try {
            return businessPartnerService
                    .getAllBusinessPartner()
                    .select(BusinessPartner.BUSINESS_PARTNER,
                            BusinessPartner.LAST_NAME,
                            BusinessPartner.FIRST_NAME,
                            BusinessPartner.IS_MALE,
                            BusinessPartner.IS_FEMALE,
                            BusinessPartner.CREATION_DATE,
                            BusinessPartner.TO_BUSINESS_PARTNER_ADDRESS
                                    .select(BusinessPartnerAddress.CITY_NAME,
                                            BusinessPartnerAddress.COUNTRY,
                                            BusinessPartnerAddress.TO_EMAIL_ADDRESS
                                                    .select(AddressEmailAddress.EMAIL_ADDRESS)
                                    )
                    )
                    .filter(BusinessPartner.BUSINESS_PARTNER_CATEGORY.eq(CATEGORY_PERSON))
                    .orderBy(BusinessPartner.LAST_NAME, Order.ASC)
                    .top(200)
                    .execute(destination);
        } catch (ODataException e) {
            throw new ResilienceRuntimeException(e);
        }
    }

Что касается фрагмента кода из DestinationService, я считаю, что метод fetchDestinationsJson() вызывает неявное исключение, таким образом давая Resilience4J знать, что что-то пошло не так. Хотя в вашем случае HttpClient не выдаст ничего при получении 404, поскольку это правильный код ответа, как и любой другой.

Я также думаю, что проверка CircuitsBreaker примеров из библиотеки Resilience4J может оказаться полезной .

Надеюсь, это поможет:)

...