首页 > 解决方案 > 问:在 SAP Cloud SDK 弹性中使用断路器

问题描述

当我尝试使用 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 中看到了以下代码。在使用 ResilienceDecorator.executeCallable() 时,它不会抛出 ResilienceRuntimeException。所以我的问题是我需要抛出 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))));

标签: connectivitycircuit-breakersap-cloud-sdk

解决方案


不,您不必抛出ResilienceRuntimeException. 实际上,SDK 仅使用它来将已检查和未检查的异常包装到未检查的异常中,该异常包装了弹性调用中发生的各种故障。

请详细说明您的问题,然后我将扩展此答案:

  • 您使用的是哪个版本的 SDK?
  • 您如何(以及多久)调用装饰的可调用对象?请展开代码块。
  • 请指定您观察到的确切行为。调用修饰的可调用对象时会引发什么异常?如果断路器打开,这应该是一个CallNotPermittedException包裹在一个ResilienceRuntimeException
  • 减少可调用以简单地抛出异常以简化代码
  • 减少弹性配置以仅使用断路器(杠杆ResilienceConfiguration.empty())。如果可行,请再次添加内容,直到无效为止。

作为参考,还请找到SDK 在后台使用弹性 4j 的文档来执行弹性操作。


推荐阅读