[Feature] Optimize feign & rest-template circuit-breaker logic (2020) . (#453)
parent
379851e4a3
commit
d31c0e2a17
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.polaris.circuitbreaker;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerProperties;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Polaris Circuit-Break Adapter .
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-11
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPolarisCircuitBreakAdapter {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractPolarisCircuitBreakAdapter.class);
|
||||||
|
|
||||||
|
protected final PolarisCircuitBreakerProperties properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor With {@link PolarisCircuitBreakerProperties} .
|
||||||
|
*
|
||||||
|
* @param properties instance of {@link PolarisCircuitBreakerProperties}.
|
||||||
|
*/
|
||||||
|
protected AbstractPolarisCircuitBreakAdapter(PolarisCircuitBreakerProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback after completion of request processing, Check if business meltdown reporting is required.
|
||||||
|
*
|
||||||
|
* @param httpStatus request http status code
|
||||||
|
* @return true , otherwise return false .
|
||||||
|
*/
|
||||||
|
protected boolean apply(@Nullable HttpStatus httpStatus) {
|
||||||
|
if (Objects.isNull(httpStatus)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// statuses > series
|
||||||
|
List<HttpStatus> status = properties.getStatuses();
|
||||||
|
|
||||||
|
if (status.isEmpty()) {
|
||||||
|
List<HttpStatus.Series> series = properties.getSeries();
|
||||||
|
// Check INTERNAL_SERVER_ERROR (500) status.
|
||||||
|
if (properties.getIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (series.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
return series.contains(HttpStatus.Series.valueOf(httpStatus));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOG.warn("Decode http status failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use the user-specified fuse status code.
|
||||||
|
return status.contains(httpStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// DEFAULT RETURN FALSE.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.polaris.circuitbreaker.config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_GATEWAY;
|
||||||
|
import static org.springframework.http.HttpStatus.BANDWIDTH_LIMIT_EXCEEDED;
|
||||||
|
import static org.springframework.http.HttpStatus.GATEWAY_TIMEOUT;
|
||||||
|
import static org.springframework.http.HttpStatus.HTTP_VERSION_NOT_SUPPORTED;
|
||||||
|
import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE;
|
||||||
|
import static org.springframework.http.HttpStatus.LOOP_DETECTED;
|
||||||
|
import static org.springframework.http.HttpStatus.NETWORK_AUTHENTICATION_REQUIRED;
|
||||||
|
import static org.springframework.http.HttpStatus.NOT_EXTENDED;
|
||||||
|
import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED;
|
||||||
|
import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE;
|
||||||
|
import static org.springframework.http.HttpStatus.VARIANT_ALSO_NEGOTIATES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of Polaris CircuitBreaker .
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-08
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("spring.cloud.polaris.circuitbreaker")
|
||||||
|
public class PolarisCircuitBreakerProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If circuit-breaker enabled.
|
||||||
|
*/
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the Http status code(s) that needs to be fused.
|
||||||
|
*/
|
||||||
|
private List<HttpStatus> statuses = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
|
||||||
|
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
|
||||||
|
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify List of HTTP status series.
|
||||||
|
*/
|
||||||
|
private List<HttpStatus.Series> series = toList(HttpStatus.Series.SERVER_ERROR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore Internal Server Error Http Status Code,
|
||||||
|
* Only takes effect if the attribute {@link PolarisCircuitBreakerProperties#series} is not empty.
|
||||||
|
*/
|
||||||
|
private Boolean ignoreInternalServerError = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert items to List.
|
||||||
|
*
|
||||||
|
* @param items item arrays
|
||||||
|
* @param <T> Object Generics.
|
||||||
|
* @return list
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
private static <T> List<T> toList(T... items) {
|
||||||
|
return new ArrayList<>(Arrays.asList(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(Boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HttpStatus> getStatuses() {
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatuses(List<HttpStatus> statuses) {
|
||||||
|
this.statuses = statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HttpStatus.Series> getSeries() {
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeries(List<HttpStatus.Series> series) {
|
||||||
|
this.series = series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getIgnoreInternalServerError() {
|
||||||
|
return ignoreInternalServerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIgnoreInternalServerError(Boolean ignoreInternalServerError) {
|
||||||
|
this.ignoreInternalServerError = ignoreInternalServerError;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.polaris.circuitbreaker;
|
||||||
|
|
||||||
|
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerProperties;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test For {@link AbstractPolarisCircuitBreakAdapter}.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a>
|
||||||
|
* @version ${project.version} - 2022/7/11
|
||||||
|
*/
|
||||||
|
public class AbstractPolarisCircuitBreakAdapterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithDefaultConfig() {
|
||||||
|
PolarisCircuitBreakerProperties properties = new PolarisCircuitBreakerProperties();
|
||||||
|
// Mock Condition
|
||||||
|
SimplePolarisCircuitBreakAdapter adapter = new SimplePolarisCircuitBreakAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithoutIgnoreInternalServerError() {
|
||||||
|
PolarisCircuitBreakerProperties properties = new PolarisCircuitBreakerProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.setIgnoreInternalServerError(false);
|
||||||
|
|
||||||
|
SimplePolarisCircuitBreakAdapter adapter = new SimplePolarisCircuitBreakAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithIgnoreInternalServerError() {
|
||||||
|
PolarisCircuitBreakerProperties properties = new PolarisCircuitBreakerProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.setIgnoreInternalServerError(true);
|
||||||
|
|
||||||
|
SimplePolarisCircuitBreakAdapter adapter = new SimplePolarisCircuitBreakAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithoutSeries() {
|
||||||
|
PolarisCircuitBreakerProperties properties = new PolarisCircuitBreakerProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.getSeries().clear();
|
||||||
|
|
||||||
|
SimplePolarisCircuitBreakAdapter adapter = new SimplePolarisCircuitBreakAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithSeries() {
|
||||||
|
PolarisCircuitBreakerProperties properties = new PolarisCircuitBreakerProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.getSeries().clear();
|
||||||
|
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
|
||||||
|
|
||||||
|
SimplePolarisCircuitBreakAdapter adapter = new SimplePolarisCircuitBreakAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Polaris CircuitBreak Adapter Implements .
|
||||||
|
*/
|
||||||
|
public static class SimplePolarisCircuitBreakAdapter extends AbstractPolarisCircuitBreakAdapter {
|
||||||
|
|
||||||
|
public SimplePolarisCircuitBreakAdapter(PolarisCircuitBreakerProperties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.rpc.enhancement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementProperties;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_GATEWAY;
|
||||||
|
import static org.springframework.http.HttpStatus.BANDWIDTH_LIMIT_EXCEEDED;
|
||||||
|
import static org.springframework.http.HttpStatus.GATEWAY_TIMEOUT;
|
||||||
|
import static org.springframework.http.HttpStatus.HTTP_VERSION_NOT_SUPPORTED;
|
||||||
|
import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE;
|
||||||
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
import static org.springframework.http.HttpStatus.LOOP_DETECTED;
|
||||||
|
import static org.springframework.http.HttpStatus.NETWORK_AUTHENTICATION_REQUIRED;
|
||||||
|
import static org.springframework.http.HttpStatus.NOT_EXTENDED;
|
||||||
|
import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED;
|
||||||
|
import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE;
|
||||||
|
import static org.springframework.http.HttpStatus.VARIANT_ALSO_NEGOTIATES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Polaris Reporter Adapter .
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-11
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPolarisReporterAdapter {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractPolarisReporterAdapter.class);
|
||||||
|
|
||||||
|
protected final RpcEnhancementProperties properties;
|
||||||
|
|
||||||
|
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
|
||||||
|
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
|
||||||
|
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor With {@link RpcEnhancementProperties} .
|
||||||
|
*
|
||||||
|
* @param properties instance of {@link RpcEnhancementProperties}.
|
||||||
|
*/
|
||||||
|
protected AbstractPolarisReporterAdapter(RpcEnhancementProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert items to List.
|
||||||
|
*
|
||||||
|
* @param items item arrays
|
||||||
|
* @param <T> Object Generics.
|
||||||
|
* @return list
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
private static <T> List<T> toList(T... items) {
|
||||||
|
return new ArrayList<>(Arrays.asList(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback after completion of request processing, Check if business meltdown reporting is required.
|
||||||
|
*
|
||||||
|
* @param httpStatus request http status code
|
||||||
|
* @return true , otherwise return false .
|
||||||
|
*/
|
||||||
|
protected boolean apply(@Nullable HttpStatus httpStatus) {
|
||||||
|
if (Objects.isNull(httpStatus)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// statuses > series
|
||||||
|
List<HttpStatus> status = properties.getStatuses();
|
||||||
|
|
||||||
|
if (status.isEmpty()) {
|
||||||
|
List<HttpStatus.Series> series = properties.getSeries();
|
||||||
|
// Check INTERNAL_SERVER_ERROR (500) status.
|
||||||
|
if (properties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (series.isEmpty()) {
|
||||||
|
return HTTP_STATUSES.contains(httpStatus);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
return series.contains(HttpStatus.Series.valueOf(httpStatus));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOG.warn("Decode http status failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use the user-specified fuse status code.
|
||||||
|
return status.contains(httpStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// DEFAULT RETURN FALSE.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.rpc.enhancement.config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of Polaris CircuitBreaker .
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-08
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("spring.cloud.tencent.rpc-enhancement")
|
||||||
|
public class RpcEnhancementProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If circuit-breaker enabled.
|
||||||
|
*/
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the Http status code(s) that needs to be fused.
|
||||||
|
*/
|
||||||
|
private List<HttpStatus> statuses = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify List of HTTP status series.
|
||||||
|
*/
|
||||||
|
private List<HttpStatus.Series> series = toList(HttpStatus.Series.SERVER_ERROR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore Internal Server Error Http Status Code,
|
||||||
|
* Only takes effect if the attribute {@link RpcEnhancementProperties#series} is not empty.
|
||||||
|
*/
|
||||||
|
private boolean ignoreInternalServerError = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert items to List.
|
||||||
|
*
|
||||||
|
* @param items item arrays
|
||||||
|
* @param <T> Object Generics.
|
||||||
|
* @return list
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
private static <T> List<T> toList(T... items) {
|
||||||
|
return new ArrayList<>(Arrays.asList(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HttpStatus> getStatuses() {
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatuses(List<HttpStatus> statuses) {
|
||||||
|
this.statuses = statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HttpStatus.Series> getSeries() {
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeries(List<HttpStatus.Series> series) {
|
||||||
|
this.series = series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIgnoreInternalServerError() {
|
||||||
|
return ignoreInternalServerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIgnoreInternalServerError(boolean ignoreInternalServerError) {
|
||||||
|
this.ignoreInternalServerError = ignoreInternalServerError;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.tencent.cloud.rpc.enhancement;
|
||||||
|
|
||||||
|
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementProperties;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test For {@link AbstractPolarisReporterAdapter}.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022/7/11
|
||||||
|
*/
|
||||||
|
public class AbstractPolarisReporterAdapterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithDefaultConfig() {
|
||||||
|
RpcEnhancementProperties properties = new RpcEnhancementProperties();
|
||||||
|
// Mock Condition
|
||||||
|
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithoutIgnoreInternalServerError() {
|
||||||
|
RpcEnhancementProperties properties = new RpcEnhancementProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.setIgnoreInternalServerError(false);
|
||||||
|
|
||||||
|
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithIgnoreInternalServerError() {
|
||||||
|
RpcEnhancementProperties properties = new RpcEnhancementProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.setIgnoreInternalServerError(true);
|
||||||
|
|
||||||
|
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithoutSeries() {
|
||||||
|
RpcEnhancementProperties properties = new RpcEnhancementProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.getSeries().clear();
|
||||||
|
|
||||||
|
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWithSeries() {
|
||||||
|
RpcEnhancementProperties properties = new RpcEnhancementProperties();
|
||||||
|
// Mock Condition
|
||||||
|
properties.getStatuses().clear();
|
||||||
|
properties.getSeries().clear();
|
||||||
|
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
|
||||||
|
|
||||||
|
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
|
||||||
|
Assertions.assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Polaris CircuitBreak Adapter Implements .
|
||||||
|
*/
|
||||||
|
public static class SimplePolarisReporterAdapter extends AbstractPolarisReporterAdapter {
|
||||||
|
|
||||||
|
public SimplePolarisReporterAdapter(RpcEnhancementProperties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue