根据文档 - https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Failover#JAX-RSFailover-Code.1,我尝试运行以下代码以及相关配置,但是一旦超过连接故障的阈值计数,断路器机制就不会打开。当电路保持关闭时,仍然接受调用尝试,这违反了预期的行为。
public class CustomerRestClient {
private CustomerRestClientFactory customerRestClientFactory;
public List<Customer> filterByFirstName(String firstName) {
List<Customer> filteredCustomers = new ArrayList<>();
CircuitBreakerFailoverFeature cbFailoverFeature = new CircuitBreakerFailoverFeature(4, 180000L);
SequentialStrategy strategy = new SequentialStrategy();
cbFailoverFeature.setStrategy(strategy);
List<Feature> featureList = new ArrayList<Feature>();
featureList.add(cbFailoverFeature);
WebClient client = customerRestClientFactory.getClient(featureList).path("/");
// Call service to get all customers
List<Customer> customers = client.get(new GenericType<List<Customer>>() {});
return filteredCustomers;
}
public void setCustomerRestClientFactory(CustomerRestClientFactory customerRestClientFactory) {
this.customerRestClientFactory = customerRestClientFactory;
}
}
public class CustomerRestClientFactory implements InitializingBean {
private List providerList; // Value is injected by Spring
private String serviceUrl; // Value is injected by Spring
public WebClient getClient(List<? extends Feature> featureList) {
if (featureList == null || featureList.isEmpty()) {
throw new IllegalArgumentException("featureList is not initialized.");
}
JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
bean.setAddress(serviceUrl);
bean.setServiceClass(WebClient.class);
bean.setProviders(providerList);
bean.setFeatures(featureList);
return bean.createWebClient();
}
}
<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd'T'HH:mm:ss"/>
</bean>
</property>
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
<bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider">
<property name="mapper" ref="objectMapper"/>
</bean>
<util:list id="providerList">
<ref bean="jsonProvider" />
<bean name="exceptionHandler" class="com.mycompany.refapp.exception.AppExceptionHandler" />
</util:list>
<bean id="customerRestClientFactory" class="com.mycompany.refapp.client.CustomerRestClientFactory">
<property name="providerList" ref="providerList" />
<property name="serviceUrl" value="${customer.rest.service.url}" />
</bean>
包含堆栈跟踪的日志(available here)。
经过大量的调试后,我开始明白连接失败的计数器永远不会超过阈值限制,因为数据的状态(包括计数器)特定于每个WebClient对象,为每个调用实例化。我假设如果在多次失败的调用中使用了相同的WebClient实例,那么计数器就会更新并最终打开电路。有关详细信息,请查找attached screenshot。
我想就我的理解是否正确得到第二个意见。
你已经并行打开了问题https://issues.apache.org/jira/browse/CXF-7663,所以我在这里分享了Colm的回复:
如果要使用Circuit-Breaker功能,则需要对所有调用使用相同的Webclient实例 - 如果要为每个调用创建一个新的WebClient,它将不起作用。这是一个测试,显示它是如何工作的: