feat:support smooth upgrade from tsf. (#1482)
parent
01d24732af
commit
6992011ed5
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.tsf.auth.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfAuth {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.auth.config;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link PolarisAuthProperties}.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class PolarisAuthPropertiesTest {
|
||||||
|
|
||||||
|
private final ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(PolarisAuthPropertiesAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.cloud.polaris.auth.enabled=false");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAndSet() {
|
||||||
|
this.applicationContextRunner.run(context -> {
|
||||||
|
PolarisAuthProperties properties = context.getBean(PolarisAuthProperties.class);
|
||||||
|
assertThat(properties.isEnabled()).isFalse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFallbackFactory.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFallbackFactory.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFallbackFactory.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFallbackFactory.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolver.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolver.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolver.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolver.java
10
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreaker.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreaker.java
10
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreaker.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreaker.java
38
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandler.java
38
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandler.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeter.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeter.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeter.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeter.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/gateway/PolarisCircuitBreakerFilterFactory.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/gateway/PolarisCircuitBreakerFilterFactory.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/gateway/PolarisCircuitBreakerFilterFactory.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/gateway/PolarisCircuitBreakerFilterFactory.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerFluxOperator.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerFluxOperator.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerFluxOperator.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerFluxOperator.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerMonoOperator.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerMonoOperator.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerMonoOperator.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerMonoOperator.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorSubscriber.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorSubscriber.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorSubscriber.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorSubscriber.java
5
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorTransformer.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorTransformer.java
5
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorTransformer.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorTransformer.java
3
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreaker.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreaker.java
3
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreaker.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreaker.java
3
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerFallback.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerFallback.java
3
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerFallback.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerFallback.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerHttpResponse.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerHttpResponse.java
55
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java
55
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateBeanPostProcessor.java
24
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java
24
spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateInterceptor.java
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.cloud.tsf.circuitbreaker.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfCircuitBreaker {
|
||||||
|
}
|
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFeignIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFeignIntegrationTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFeignIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFeignIntegrationTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolverTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolverTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolverTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolverTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeterTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeterTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeterTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeterTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/gateway/PolarisCircuitBreakerGatewayIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/gateway/PolarisCircuitBreakerGatewayIntegrationTest.java
2
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/gateway/PolarisCircuitBreakerGatewayIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/gateway/PolarisCircuitBreakerGatewayIntegrationTest.java
130
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateIntegrationTest.java
130
spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerRestTemplateIntegrationTest.java → spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerRestTemplateIntegrationTest.java
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.discovery.refresh;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.pojo.Instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for service instance change.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public interface ServiceInstanceChangeCallback {
|
||||||
|
|
||||||
|
void callback(List<Instance> currentServiceInstances, List<Instance> addServiceInstances, List<Instance> deleteServiceInstances);
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.discovery.refresh;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
|
||||||
|
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
|
||||||
|
import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
|
||||||
|
import com.tencent.polaris.api.pojo.Instance;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.polaris.client.util.NamedThreadFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import reactor.util.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call back manager for service instance change.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class ServiceInstanceChangeCallbackManager implements ApplicationListener<ApplicationReadyEvent>, BeanPostProcessor {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ServiceInstanceChangeCallbackManager.class);
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, List<ServiceInstanceChangeCallback>> callbackMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final ScheduledThreadPoolExecutor serviceChangeListenerExecutor;
|
||||||
|
|
||||||
|
public ServiceInstanceChangeCallbackManager() {
|
||||||
|
this.serviceChangeListenerExecutor = new ScheduledThreadPoolExecutor(4, new NamedThreadFactory("service-change-listener"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(String serviceName, List<Instance> oldInstances, List<Instance> newInstances) {
|
||||||
|
|
||||||
|
List<Instance> addInstances = new ArrayList<>();
|
||||||
|
List<Instance> deleteInstances = new ArrayList<>();
|
||||||
|
|
||||||
|
// calculate add instances.
|
||||||
|
for (Instance instance : newInstances) {
|
||||||
|
if (!oldInstances.contains(instance)) {
|
||||||
|
addInstances.add(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// calculate delete instances.
|
||||||
|
for (Instance instance : oldInstances) {
|
||||||
|
if (!newInstances.contains(instance)) {
|
||||||
|
deleteInstances.add(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!CollectionUtils.isEmpty(addInstances) || !CollectionUtils.isEmpty(deleteInstances))
|
||||||
|
&& callbackMap.containsKey(serviceName)) {
|
||||||
|
List<ServiceInstanceChangeCallback> callbacks = callbackMap.get(serviceName);
|
||||||
|
|
||||||
|
for (ServiceInstanceChangeCallback callback : callbacks) {
|
||||||
|
serviceChangeListenerExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
callback.callback(newInstances, addInstances, deleteInstances);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOG.error("exception in callback, service name:{}, ", serviceName, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||||
|
Class<?> clz = bean.getClass();
|
||||||
|
|
||||||
|
if (!ServiceInstanceChangeCallback.class.isAssignableFrom(clz)) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
String serviceName = null;
|
||||||
|
if (clz.isAnnotationPresent(ServiceInstanceChangeListener.class)) {
|
||||||
|
ServiceInstanceChangeListener serviceInstanceChangeListener = clz.getAnnotation(ServiceInstanceChangeListener.class);
|
||||||
|
serviceName = serviceInstanceChangeListener.serviceName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(serviceName)) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process callback
|
||||||
|
if (callbackMap.containsKey(serviceName)) {
|
||||||
|
List<ServiceInstanceChangeCallback> callbacks = callbackMap.get(serviceName);
|
||||||
|
callbacks.add((ServiceInstanceChangeCallback) bean);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List<ServiceInstanceChangeCallback> callbacks = new ArrayList<>();
|
||||||
|
callbacks.add((ServiceInstanceChangeCallback) bean);
|
||||||
|
callbackMap.put(serviceName, callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(@NonNull ApplicationReadyEvent event) {
|
||||||
|
PolarisDiscoveryClient polarisDiscoveryClient = ApplicationContextAwareUtils.getBeanIfExists(PolarisDiscoveryClient.class);
|
||||||
|
PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient = ApplicationContextAwareUtils.getBeanIfExists(PolarisReactiveDiscoveryClient.class);
|
||||||
|
for (String serviceName : callbackMap.keySet()) {
|
||||||
|
try {
|
||||||
|
if (polarisDiscoveryClient != null) {
|
||||||
|
polarisDiscoveryClient.getInstances(serviceName);
|
||||||
|
}
|
||||||
|
else if (polarisReactiveDiscoveryClient != null) {
|
||||||
|
polarisReactiveDiscoveryClient.getInstances(serviceName).subscribe();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.warn("[{}] no discovery client found.", serviceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable throwable) {
|
||||||
|
LOG.error("Get instances of service [{}] failed.", serviceName, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.discovery.refresh;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Component
|
||||||
|
public @interface ServiceInstanceChangeListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* listen service name.
|
||||||
|
*/
|
||||||
|
String serviceName();
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.eager.config;
|
||||||
|
|
||||||
|
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
|
||||||
|
import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
|
||||||
|
import com.tencent.cloud.polaris.eager.instrument.feign.FeignEagerLoadSmartLifecycle;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(name = "spring.cloud.polaris.discovery.eager-load.enabled", havingValue = "true")
|
||||||
|
public class PolarisEagerLoadAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnClass(name = "feign.Feign")
|
||||||
|
@ConditionalOnProperty(name = "spring.cloud.polaris.discovery.eager-load.feign.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public FeignEagerLoadSmartLifecycle feignEagerLoadSmartLifecycle(
|
||||||
|
ApplicationContext applicationContext, @Autowired(required = false) PolarisDiscoveryClient polarisDiscoveryClient,
|
||||||
|
@Autowired(required = false) PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient) {
|
||||||
|
return new FeignEagerLoadSmartLifecycle(applicationContext, polarisDiscoveryClient, polarisReactiveDiscoveryClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.eager.instrument.feign;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.FeignUtil;
|
||||||
|
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
|
||||||
|
import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.SmartLifecycle;
|
||||||
|
|
||||||
|
public class FeignEagerLoadSmartLifecycle implements SmartLifecycle {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(FeignEagerLoadSmartLifecycle.class);
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final PolarisDiscoveryClient polarisDiscoveryClient;
|
||||||
|
|
||||||
|
private final PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient;
|
||||||
|
|
||||||
|
public FeignEagerLoadSmartLifecycle(ApplicationContext applicationContext, PolarisDiscoveryClient polarisDiscoveryClient,
|
||||||
|
PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.polarisDiscoveryClient = polarisDiscoveryClient;
|
||||||
|
this.polarisReactiveDiscoveryClient = polarisReactiveDiscoveryClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
LOG.info("feign eager-load start");
|
||||||
|
for (String name : applicationContext.getBeanDefinitionNames()) {
|
||||||
|
try {
|
||||||
|
if (name.contains(FeignUtil.FEIGN_CLIENT_SPECIF) && !name.startsWith(FeignUtil.FEIGN_CLIENT_DEFAULT)) {
|
||||||
|
String feignName = FeignUtil.analysisFeignName(name, applicationContext);
|
||||||
|
if (StringUtils.isNotBlank(feignName)) {
|
||||||
|
LOG.info("[{}] eager-load start", feignName);
|
||||||
|
if (polarisDiscoveryClient != null) {
|
||||||
|
polarisDiscoveryClient.getInstances(feignName);
|
||||||
|
}
|
||||||
|
else if (polarisReactiveDiscoveryClient != null) {
|
||||||
|
polarisReactiveDiscoveryClient.getInstances(feignName).subscribe();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.warn("[{}] no discovery client found.", feignName);
|
||||||
|
}
|
||||||
|
LOG.info("[{}] eager-load end", feignName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.warn("feign name is blank.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOG.error("[{}] eager-load failed.", name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.info("feign eager-load end");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRunning() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPhase() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.serviceregistry.watch;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.ecwid.consul.v1.health.model.HealthService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not working anymore. Compatible with old versions TSF SDK.
|
||||||
|
* <p>
|
||||||
|
* Deprecated since 2.0.0.0.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public interface ConsulServiceChangeCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调函数.
|
||||||
|
*/
|
||||||
|
void callback(List<HealthService> currentServices, List<HealthService> addServices, List<HealthService> deleteServices);
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.tsf.ratelimit.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfRateLimit {
|
||||||
|
}
|
2
spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java → spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptor.java
2
spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java → spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptor.java
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.lane.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfLane {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.femas.adaptor.tsf.governance.zonefilter;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfZoneFilter {
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.unit.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfUnit {
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.unit.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface TsfUnitCall {
|
||||||
|
|
||||||
|
// 单元化下的业务系统名
|
||||||
|
String systemName() default "";
|
||||||
|
|
||||||
|
// 单元化下的是否调用GDU服务
|
||||||
|
boolean global() default false;
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.unit.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface TsfUnitCustomerIdentifier {
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.unit.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface TsfUnitLocalCall {
|
||||||
|
String className() default "";
|
||||||
|
|
||||||
|
String methodName() default "";
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.cloud.tsf.route.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfRoute {
|
||||||
|
}
|
||||||
|
|
2
spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java → spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptorTest.java
2
spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java → spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptorTest.java
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.common.async;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.threadlocal.TaskExecutorWrapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
|
import org.springframework.core.task.TaskExecutor;
|
||||||
|
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_CONSUMER;
|
||||||
|
import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_SUPPLIER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polaris async executor for @Async .
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
|
@ConditionalOnProperty(name = "spring.cloud.tencent.async.enabled")
|
||||||
|
public class PolarisAsyncConfiguration implements AsyncConfigurer {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PolarisAsyncConfiguration.class);
|
||||||
|
|
||||||
|
@Primary
|
||||||
|
@Bean("polarisAsyncExecutor")
|
||||||
|
public TaskExecutor polarisAsyncExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
int corePoolSize = 10;
|
||||||
|
executor.setCorePoolSize(corePoolSize);
|
||||||
|
int maxPoolSize = 50;
|
||||||
|
executor.setMaxPoolSize(maxPoolSize);
|
||||||
|
int queueCapacity = 10;
|
||||||
|
executor.setQueueCapacity(queueCapacity);
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
String threadNamePrefix = "polaris-async-executor-";
|
||||||
|
executor.setThreadNamePrefix(threadNamePrefix);
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(5);
|
||||||
|
executor.initialize();
|
||||||
|
TaskExecutor executorWrapper = new TaskExecutorWrapper<>(executor, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
|
||||||
|
logger.info("Created async executor with corePoolSize:{}, maxPoolSize:{}, queueCapacity:{}", corePoolSize, maxPoolSize, queueCapacity);
|
||||||
|
return executorWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor getAsyncExecutor() {
|
||||||
|
return polarisAsyncExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||||
|
return (ex, method, params) -> logger.error("Execute asynchronous tasks '{}' failed.", method, ex);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.common.metadata;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.JacksonUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata Context for cross thread.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class CrossThreadMetadataContext {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(CrossThreadMetadataContext.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get metadata context from previous thread.
|
||||||
|
*/
|
||||||
|
public static final Supplier<CrossThreadMetadataContext> CROSS_THREAD_METADATA_CONTEXT_SUPPLIER = () -> {
|
||||||
|
CrossThreadMetadataContext crossThreadMetadataContext = new CrossThreadMetadataContext();
|
||||||
|
crossThreadMetadataContext.setMetadataContext(MetadataContextHolder.get());
|
||||||
|
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("Context map is got: {}", JacksonUtils.serialize2Json(crossThreadMetadataContext));
|
||||||
|
}
|
||||||
|
return crossThreadMetadataContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set metadata context to current thread.
|
||||||
|
*/
|
||||||
|
public static final Consumer<CrossThreadMetadataContext> CROSS_THREAD_METADATA_CONTEXT_CONSUMER = crossThreadMetadataContext -> {
|
||||||
|
MetadataContextHolder.set(crossThreadMetadataContext.getMetadataContext());
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("Context map is set: {}", JacksonUtils.serialize2Json(crossThreadMetadataContext));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private MetadataContext metadataContext;
|
||||||
|
|
||||||
|
public MetadataContext getMetadataContext() {
|
||||||
|
return metadataContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadataContext(MetadataContext metadataContext) {
|
||||||
|
this.metadataContext = metadataContext;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.common.util;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author heihuliliu
|
||||||
|
*/
|
||||||
|
public final class FeignUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feign client spec.
|
||||||
|
*/
|
||||||
|
public static final String FEIGN_CLIENT_SPECIF = ".FeignClientSpecification";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Feign client spec.
|
||||||
|
*/
|
||||||
|
public static final String FEIGN_CLIENT_DEFAULT = "default.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regular expression that parses ${xxx} .
|
||||||
|
*/
|
||||||
|
public static final String REGEX = "^[$][{](.*)[}]$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replacement of ${xxx}.
|
||||||
|
*/
|
||||||
|
public static final String REPLACEMENT = "$1";
|
||||||
|
|
||||||
|
private FeignUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO If @FeignClient specifies contextId, the service name will not be obtained correctly, but the contextId will be obtained.
|
||||||
|
*
|
||||||
|
* @param name feign name.
|
||||||
|
* @param context application context.
|
||||||
|
* @return service name.
|
||||||
|
*/
|
||||||
|
public static String analysisFeignName(String name, ApplicationContext context) {
|
||||||
|
String feignName = "";
|
||||||
|
String feignPath = name.substring(0, name.indexOf(FEIGN_CLIENT_SPECIF));
|
||||||
|
// Handle the case where the service name is a variable
|
||||||
|
if (feignPath.matches(REGEX)) {
|
||||||
|
feignPath = context.getEnvironment().getProperty(feignPath.replaceAll(REGEX, REPLACEMENT));
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(feignPath)) {
|
||||||
|
// The case of multi-level paths
|
||||||
|
String[] feignNames = feignPath.split("/");
|
||||||
|
if (feignNames.length > 1) {
|
||||||
|
for (int i = 0; i < feignNames.length; i++) {
|
||||||
|
if (StringUtils.hasText(feignNames[i])) {
|
||||||
|
feignName = feignNames[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
feignName = feignNames[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return feignName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.common.util;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.tencent.polaris.threadlocal.cross.CompletableFutureUtils;
|
||||||
|
|
||||||
|
import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_CONSUMER;
|
||||||
|
import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_SUPPLIER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polaris CompletableFuture Utils.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public final class PolarisCompletableFutureUtils {
|
||||||
|
|
||||||
|
private PolarisCompletableFutureUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
|
||||||
|
return CompletableFutureUtils.supplyAsync(supplier, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<Void> runAsync(Runnable runnable) {
|
||||||
|
return CompletableFutureUtils.runAsync(runnable, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.tsf.core.util;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring context utils.
|
||||||
|
* <p>
|
||||||
|
* Deprecated since 2.0.0.0.
|
||||||
|
*
|
||||||
|
* @author hongweizhu
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public class TsfSpringContextAware {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get application context.
|
||||||
|
* @return application context
|
||||||
|
*/
|
||||||
|
public static ApplicationContext getApplicationContext() {
|
||||||
|
return ApplicationContextAwareUtils.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
// do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get application property.
|
||||||
|
* @param key property name
|
||||||
|
* @return property value
|
||||||
|
*/
|
||||||
|
public static String getProperties(String key) {
|
||||||
|
return ApplicationContextAwareUtils.getProperties(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get application property. If null, return default.
|
||||||
|
* @param key property name
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return property value
|
||||||
|
*/
|
||||||
|
public static String getProperties(String key, String defaultValue) {
|
||||||
|
return ApplicationContextAwareUtils.getProperties(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T getBean(Class<T> requiredType) {
|
||||||
|
return ApplicationContextAwareUtils.getBean(requiredType);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.quickstart.callee.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.tencent.cloud.polaris.discovery.refresh.ServiceInstanceChangeCallback;
|
||||||
|
import com.tencent.cloud.polaris.discovery.refresh.ServiceInstanceChangeListener;
|
||||||
|
import com.tencent.polaris.api.pojo.Instance;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call back for QuickstartCalleeService.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@ServiceInstanceChangeListener(serviceName = "QuickstartCalleeService")
|
||||||
|
public class CalleeServiceChangeCallback implements ServiceInstanceChangeCallback {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(CalleeServiceChangeCallback.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void callback(List<Instance> currentServiceInstances, List<Instance> addServiceInstances, List<Instance> deleteServiceInstances) {
|
||||||
|
String current = generateNodeList(currentServiceInstances);
|
||||||
|
String add = generateNodeList(addServiceInstances);
|
||||||
|
String delete = generateNodeList(deleteServiceInstances);
|
||||||
|
LOG.info("current: {}, add: {}, delete: {}", current, add, delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateNodeList(List<Instance> deleteServiceInstances) {
|
||||||
|
StringBuilder nodeListStr = new StringBuilder("[");
|
||||||
|
for (Instance instance : deleteServiceInstances) {
|
||||||
|
if (nodeListStr.length() > 1) {
|
||||||
|
nodeListStr.append(", ");
|
||||||
|
}
|
||||||
|
nodeListStr.append(instance.getHost()).append(":").append(instance.getPort());
|
||||||
|
}
|
||||||
|
nodeListStr.append("]");
|
||||||
|
return nodeListStr.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.quickstart.callee.service;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance;
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for fault tolerance.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FaultToleranceService {
|
||||||
|
|
||||||
|
private final AtomicInteger failOverCount = new AtomicInteger(0);
|
||||||
|
private final AtomicInteger forkingCount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
@FaultTolerance(strategy = FaultToleranceStrategy.FAIL_FAST, fallbackMethod = "fallback")
|
||||||
|
public String failFast() {
|
||||||
|
throw new RuntimeException("NO");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String fallback() {
|
||||||
|
return "fallback";
|
||||||
|
}
|
||||||
|
|
||||||
|
@FaultTolerance(strategy = FaultToleranceStrategy.FAIL_OVER, maxAttempts = 3)
|
||||||
|
public String failOver() {
|
||||||
|
if (failOverCount.incrementAndGet() % 4 == 0) {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
throw new RuntimeException("NO");
|
||||||
|
}
|
||||||
|
|
||||||
|
@FaultTolerance(strategy = FaultToleranceStrategy.FORKING, parallelism = 4)
|
||||||
|
public String forking() {
|
||||||
|
if (forkingCount.incrementAndGet() % 4 == 0) {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
throw new RuntimeException("NO");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.tsf.demo.consumer.controller;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.tsf.core.TsfContext;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class SdkBaseTest {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(SdkBaseTest.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
|
// 调用一次provider接口
|
||||||
|
@RequestMapping(value = "/echo-once/{str}", method = RequestMethod.GET)
|
||||||
|
public String restOnceProvider(@PathVariable String str,
|
||||||
|
@RequestParam(required = false) String tagName,
|
||||||
|
@RequestParam(required = false) String tagValue) {
|
||||||
|
if (!StringUtils.isEmpty(tagName)) {
|
||||||
|
TsfContext.putTag(tagName, tagValue);
|
||||||
|
}
|
||||||
|
LOG.info("start call echo-once");
|
||||||
|
String result = restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
|
||||||
|
LOG.info("end call echo-once, the result is : " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-tencent-plugin-starters</artifactId>
|
||||||
|
<groupId>com.tencent.cloud</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-starter-tencent-fault-tolerance</artifactId>
|
||||||
|
<name>Spring Cloud Starter Tencent Fault Tolerance Plugin</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.plugin.faulttolerance.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for Fault Tolerance.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface FaultTolerance {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a method to process fallback logic.
|
||||||
|
* A fallback method should be defined in the same class where is @FaultTolerance.
|
||||||
|
* Also a fallback method should have same signature to a method.
|
||||||
|
* for example:
|
||||||
|
* <p>
|
||||||
|
* <pre>
|
||||||
|
* @FaultTolerance(fallbackMethod = "getByIdFallback")
|
||||||
|
* public String getById(String id) {
|
||||||
|
* // original method implementation
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public String getByIdFallback(String id) {
|
||||||
|
* // fallback method implementation
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* </p>
|
||||||
|
* @return method name
|
||||||
|
*/
|
||||||
|
String fallbackMethod() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines exceptions which should be ignored.
|
||||||
|
*
|
||||||
|
* @return exceptions to ignore
|
||||||
|
*/
|
||||||
|
Class<? extends Throwable>[] ignoreExceptions() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines exceptions which should be retried.
|
||||||
|
* Default is all exceptions.
|
||||||
|
*
|
||||||
|
* @return exceptions to wrap
|
||||||
|
*/
|
||||||
|
Class<? extends Throwable>[] raisedExceptions() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the fault tolerance strategy, the default is fast fail strategy.
|
||||||
|
* @see FaultToleranceStrategy
|
||||||
|
*/
|
||||||
|
FaultToleranceStrategy strategy() default FaultToleranceStrategy.FAIL_FAST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of retries, only used under {@link FaultToleranceStrategy}.FAIL_OVER strategy. Default is 0.
|
||||||
|
*/
|
||||||
|
int maxAttempts() default 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parallelism of forking is only used under the {@link FaultToleranceStrategy}.FORKING strategy.
|
||||||
|
*/
|
||||||
|
int parallelism() default 1;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.plugin.faulttolerance.common;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback method for fault-tolerance.
|
||||||
|
*
|
||||||
|
* @author zhixinzxliu
|
||||||
|
*/
|
||||||
|
public class FallbackMethod {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absent fallback method.
|
||||||
|
*/
|
||||||
|
public static final FallbackMethod ABSENT = new FallbackMethod(null);
|
||||||
|
|
||||||
|
private final Method method;
|
||||||
|
|
||||||
|
public FallbackMethod(Method method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.plugin.faulttolerance.config;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.instrument.FaultToleranceAspect;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FaultTolerance Auto-Configuration.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
|
public class FaultToleranceAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public FaultToleranceAspect faultToleranceAspect() {
|
||||||
|
return new FaultToleranceAspect();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.plugin.faulttolerance.instrument;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance;
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.common.FallbackMethod;
|
||||||
|
import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.cloud.tsf.faulttolerance.annotation.TsfFaultTolerance;
|
||||||
|
import org.springframework.cloud.tsf.faulttolerance.model.TsfFaultToleranceStragety;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fault tolerance.
|
||||||
|
*
|
||||||
|
* @author zhixinzxliu, Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
public class FaultToleranceAspect {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FaultToleranceAspect.class);
|
||||||
|
|
||||||
|
private final Map<Method, FallbackMethod> fallbackMethodMap = new ConcurrentHashMap<>();
|
||||||
|
private final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
|
@Pointcut("@annotation(org.springframework.cloud.tsf.faulttolerance.annotation.TsfFaultTolerance)"
|
||||||
|
+ " || @annotation(com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance)")
|
||||||
|
public void faultToleranceAnnotationPointcut() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("faultToleranceAnnotationPointcut()")
|
||||||
|
public Object methodsAnnotatedWithFaultTolerance(final ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
FaultTolerance faultTolerance = signature.getMethod().getAnnotation(FaultTolerance.class);
|
||||||
|
TsfFaultTolerance tsfFaultTolerance = signature.getMethod().getAnnotation(TsfFaultTolerance.class);
|
||||||
|
|
||||||
|
Object result;
|
||||||
|
try {
|
||||||
|
// Invoke job in parallel. Whoever returns the result first will use it.
|
||||||
|
// The latter result will be ignored directly.
|
||||||
|
// If all exceptions occur, an exception will be thrown.
|
||||||
|
if (faultTolerance != null
|
||||||
|
&& faultTolerance.strategy() == FaultToleranceStrategy.FORKING
|
||||||
|
&& faultTolerance.parallelism() > 1) {
|
||||||
|
List<Callable<Object>> jobs = generateJobs(faultTolerance.parallelism(), joinPoint);
|
||||||
|
result = executorService.invokeAny(jobs);
|
||||||
|
}
|
||||||
|
else if (tsfFaultTolerance != null &&
|
||||||
|
tsfFaultTolerance.strategy() == TsfFaultToleranceStragety.FORKING &&
|
||||||
|
tsfFaultTolerance.parallelism() > 1) {
|
||||||
|
List<Callable<Object>> jobs = generateJobs(tsfFaultTolerance.parallelism(), joinPoint);
|
||||||
|
result = executorService.invokeAny(jobs);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = joinPoint.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable throwable) {
|
||||||
|
return execFaultToleranceLogic(joinPoint, faultTolerance, tsfFaultTolerance, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object execFaultToleranceLogic(ProceedingJoinPoint joinPoint, FaultTolerance faultTolerance, TsfFaultTolerance tsfFaultTolerance, Throwable throwable) throws Throwable {
|
||||||
|
if (!needExecuteFaultTolerance(faultTolerance, tsfFaultTolerance, throwable)) {
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重试逻辑
|
||||||
|
if ((faultTolerance != null && faultTolerance.strategy() == FaultToleranceStrategy.FAIL_OVER)
|
||||||
|
|| (tsfFaultTolerance != null && tsfFaultTolerance.strategy() == TsfFaultToleranceStragety.FAIL_OVER)) {
|
||||||
|
int maxAttempts = faultTolerance != null ? faultTolerance.maxAttempts() : tsfFaultTolerance.maxAttempts();
|
||||||
|
while (maxAttempts > 0) {
|
||||||
|
try {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
catch (Throwable throwable1) {
|
||||||
|
if (!needExecuteFaultTolerance(faultTolerance, tsfFaultTolerance, throwable1)) {
|
||||||
|
throw throwable1;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error("The {} time retry error, will continue retry {} times.", maxAttempts, maxAttempts - 1, throwable1);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
maxAttempts--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
if (method == null) {
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
FallbackMethod fallbackMethod = fallbackMethodMap.get(method);
|
||||||
|
if (fallbackMethod == null) {
|
||||||
|
fallbackMethod = resolveFallbackMethod(joinPoint);
|
||||||
|
fallbackMethodMap.putIfAbsent(method, fallbackMethod);
|
||||||
|
}
|
||||||
|
if (fallbackMethod.getMethod() != null) {
|
||||||
|
return fallbackMethod.getMethod().invoke(joinPoint.getTarget(), joinPoint.getArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Callable<Object>> generateJobs(int parallelism, final ProceedingJoinPoint joinPoint) {
|
||||||
|
List<Callable<Object>> jobs = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < parallelism; i++) {
|
||||||
|
jobs.add(() -> {
|
||||||
|
try {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
throw new RuntimeException(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. If the user sets ignoreExceptions and the current exception is a subclass of one of them,
|
||||||
|
* the fault-tolerant logic will not be executed.<br>
|
||||||
|
* 2. If the user does not set ignoreExceptions or the current exception is not a subclass of ignoreExceptions
|
||||||
|
* and meets the following conditions, fault-tolerant logic will be executed:<br>
|
||||||
|
* 2.1. If the user does not set raisedExceptions, fault tolerance logic will be executed.<br>
|
||||||
|
* 2.2. The user has set raisedExceptions, and the current exception is a subclass of one of the raisedExceptions set by the user.
|
||||||
|
*/
|
||||||
|
private boolean needExecuteFaultTolerance(FaultTolerance faultTolerance, TsfFaultTolerance tsfFaultTolerance, Throwable throwable) {
|
||||||
|
if (faultTolerance == null && tsfFaultTolerance == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Class<? extends Throwable>[] ignoreExceptions = faultTolerance != null ? faultTolerance.ignoreExceptions() : null;
|
||||||
|
if (ignoreExceptions == null || ignoreExceptions.length == 0) {
|
||||||
|
ignoreExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.ignoreExceptions() : null;
|
||||||
|
}
|
||||||
|
Class<? extends Throwable>[] raisedExceptions = faultTolerance != null ? faultTolerance.raisedExceptions() : null;
|
||||||
|
if (raisedExceptions == null || raisedExceptions.length == 0) {
|
||||||
|
raisedExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.raisedExceptions() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (ignoreExceptions != null) {
|
||||||
|
for (Class<? extends Throwable> ignoreException : ignoreExceptions) {
|
||||||
|
if (ignoreException.isAssignableFrom(throwable.getClass())) {
|
||||||
|
logger.debug("The exception {} is ignored.", throwable.getClass().getName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raisedExceptions == null || raisedExceptions.length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (Class<? extends Throwable> raisedException : raisedExceptions) {
|
||||||
|
if (raisedException.isAssignableFrom(throwable.getClass())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable throwable1) {
|
||||||
|
logger.warn("Check exception {} failed.", throwable.getClass().getName(), throwable1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FallbackMethod resolveFallbackMethod(ProceedingJoinPoint joinPoint) {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
FaultTolerance faultTolerance = signature.getMethod().getAnnotation(FaultTolerance.class);
|
||||||
|
TsfFaultTolerance tsfFaultTolerance = signature.getMethod().getAnnotation(TsfFaultTolerance.class);
|
||||||
|
|
||||||
|
String fallbackMethodName = faultTolerance != null ? faultTolerance.fallbackMethod() : tsfFaultTolerance.fallbackMethod();
|
||||||
|
Class<?> targetClass = joinPoint.getTarget().getClass();
|
||||||
|
Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
|
||||||
|
|
||||||
|
Method method = getDeclaredMethodFor(targetClass, fallbackMethodName, false, parameterTypes);
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
return FallbackMethod.ABSENT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (signature.getMethod().getReturnType().isAssignableFrom(method.getReturnType())) {
|
||||||
|
return new FallbackMethod(method);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return FallbackMethod.ABSENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method getDeclaredMethodFor(Class<?> clazz, String name, boolean inRecursive, Class<?>... parameterTypes) {
|
||||||
|
try {
|
||||||
|
return clazz.getDeclaredMethod(name, parameterTypes);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
if (!inRecursive) {
|
||||||
|
logger.warn("Fallback method not found! Classname = {}, methodName = {}, parameterTypes = {}",
|
||||||
|
clazz.getName(), name, Arrays.toString(parameterTypes));
|
||||||
|
}
|
||||||
|
Class<?> superClass = clazz.getSuperclass();
|
||||||
|
if (superClass != null) {
|
||||||
|
return getDeclaredMethodFor(superClass, name, true, parameterTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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.plugin.faulttolerance.model;
|
||||||
|
|
||||||
|
public enum FaultToleranceStrategy {
|
||||||
|
/**
|
||||||
|
* Fails directly. For downstream services without idempotence, fail fast is recommended.
|
||||||
|
*/
|
||||||
|
FAIL_FAST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the request is wrong, it will be retried.
|
||||||
|
*/
|
||||||
|
FAIL_OVER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sending multiple requests at the same time requires the user to configure the degree of parallelism.
|
||||||
|
* For example, if two requests are sent at the same time, whichever one returns first will return the result.
|
||||||
|
* If the first request is an exception, it will wait for another request, and if all are exceptions, an exception will be returned.
|
||||||
|
*/
|
||||||
|
FORKING
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty annotation. Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface EnableTsfFaultTolerance {
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation allows specify TsfFaultTolerance properties in the following format:
|
||||||
|
* property name = property value.
|
||||||
|
*
|
||||||
|
* @author zhixinzxliu
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
public @interface TsfFaultToleranceProperty {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property name.
|
||||||
|
*
|
||||||
|
* @return name
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property value.
|
||||||
|
*
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.model;
|
||||||
|
|
||||||
|
@Deprecated(since = "2.0.0.0")
|
||||||
|
public enum TsfFaultToleranceStragety {
|
||||||
|
/**
|
||||||
|
* Fails directly. For downstream services without idempotence, fail fast is recommended.
|
||||||
|
*/
|
||||||
|
FAIL_FAST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the request is wrong, it will be retried.
|
||||||
|
*/
|
||||||
|
FAIL_OVER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sending multiple requests at the same time requires the user to configure the degree of parallelism.
|
||||||
|
* For example, if two requests are sent at the same time, whichever one returns first will return the result.
|
||||||
|
* If the first request is an exception, it will wait for another request, and if all are exceptions, an exception will be returned.
|
||||||
|
*/
|
||||||
|
FORKING
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue