Connectivity Q:在SAP Cloud SDK中使用断路器

Connectivity Q:在SAP Cloud SDK中使用断路器,connectivity,circuit-breaker,sap-cloud-sdk,Connectivity,Circuit Breaker,Sap Cloud Sdk,当我尝试使用ResilienceDecorator.executeCallable()启用断路器时,我必须在我的调用中抛出ResilienceRuntimeException,以使断路器工作。示例代码如下。没有它,断路器总是闭合的。这样做对吗 response = ResilienceDecorator.executeCallable(() -> { HttpResponse response1 = tryHttpClient.get().execute(request);

当我尝试使用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。所以我的问题是,我是否需要将弹性排除在异常之外,以使断路器工作?如果我不需要,我的代码有什么错误吗

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))));
史蒂文

我在这一特定部分不是最有经验的,但看看你的代码,我觉得它很好。当服务器返回
404notfound
时,这并不是服务失败或错误的指示,而是资源根本找不到。如果在您的案例中,
404
意味着发生了错误,并且必须使用
弹性方法重试请求,则您必须抛出该异常以通知弹性4j smth出错

在我们努力改进文档的同时,我建议您看看现有的。为了清晰起见,我们还抛出了
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);
        }
    }
public List execute(){
返回ResilienceDecorator.executeSupplier(this::run,myResilienceConfig,e->{
logger.warn(“由于异常而调用了回退。”,e);
返回集合。emptyList();
});
}
私有列表运行(){
试一试{
返回businessPartnerService
.getAllBusinessPartner()
.选择(业务伙伴。业务伙伴,
业务伙伴。姓氏,
业务伙伴。姓名,
业务伙伴是男,
商业伙伴是女性,
BusinessPartner.CREATION_日期,
业务伙伴。收件人:业务伙伴地址
.选择(BusinessPartnerAddress.CITY\u名称,
BusinessPartnerAddress.COUNTRY,
BusinessPartnerAddress.TO_电子邮件地址
.选择(AddressEmailAddress.EMAIL\u地址)
)
)
.filter(BusinessPartner.BusinessPartner\u CATEGORY.eq(CATEGORY\u PERSON))
.orderBy(BusinessPartner.LAST_NAME,Order.ASC)
.top(200)
.执行(目的地);
}捕获(ODataException e){
抛出新的ResilienceRuntimeException(e);
}
}
关于
DestinationService
中的代码片段,我相信
fetchDestinationsJson()
方法会抛出一个隐式异常,从而让Resilience4J知道smth出错了。而在您的情况下,HttpClient在接收到
404
时不会抛出任何东西,因为它与其他代码一样是正确的响应代码

我还认为检查
电路断路器


我希望它有帮助:)

不,您不必抛出
ResilienceRuntimeException
。事实上,SDK只使用它将选中和未选中的异常包装成未选中的异常,该异常包装了弹性调用中发生的各种故障

请用更多细节展开您的问题,然后我将展开此答案:

  • 您正在使用哪个版本的SDK
  • 如何(以及多久一次)调用修饰的callable?请展开代码块
  • 请详细说明您观察到的确切行为。调用修饰的可调用函数时会引发什么异常?如果断路器断开,这应该是一个
    CallNotPermittedException
    包裹在
    ResilienceRuntimeException
  • 减少可调用性,以便简单地抛出异常,从而简化代码
  • 将弹性配置减少为仅使用断路器(利用
    ResilienceConfiguration.empty()
    )。如果这样做有效,请重新添加内容,直到它不起作用
还请查找SDK在引擎盖下用于执行弹性操作的