commit
3da3aa869d
@ -0,0 +1,13 @@
|
||||
# Change Log
|
||||
---
|
||||
|
||||
- [fix: add gateway context config example.](https://github.com/Tencent/spring-cloud-tencent/pull/1563)
|
||||
- [feat:support config empty protection.](https://github.com/Tencent/spring-cloud-tencent/pull/1585)
|
||||
- [feat:upgrade springframework version.](https://github.com/Tencent/spring-cloud-tencent/pull/1590)
|
||||
- [feat:support dynamic multi-discovery.](https://github.com/Tencent/spring-cloud-tencent/pull/1595)
|
||||
- [feat:support ipv6.](https://github.com/Tencent/spring-cloud-tencent/pull/1598)
|
||||
- [feat:support config all recover enabled.](https://github.com/Tencent/spring-cloud-tencent/pull/1604)
|
||||
- [feat:support stat reporting path aggregation.](https://github.com/Tencent/spring-cloud-tencent/pull/1608)
|
||||
- [feat:support instance detect.](https://github.com/Tencent/spring-cloud-tencent/pull/1617)
|
||||
- [fix: fix loadbalancer metadata type.](https://github.com/Tencent/spring-cloud-tencent/pull/1625)
|
||||
- [feat:support polaris server nearby backup LB.](https://github.com/Tencent/spring-cloud-tencent/pull/1627)
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.circuitbreaker.beanprocessor;
|
||||
|
||||
import com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate.PolarisLoadBalancerInterceptor;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* LoadBalancerInterceptorBeanPostProcessor is used to wrap the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class LoadBalancerInterceptorBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware, Ordered {
|
||||
/**
|
||||
* The order of the bean post processor. if user want to wrap it(CustomLoadBalancerInterceptor -> PolarisLoadBalancerInterceptor), CustomLoadBalancerInterceptorBeanPostProcessor's order should be bigger than ${@link POLARIS_LOAD_BALANCER_INTERCEPTOR_POST_PROCESSOR_ORDER}.
|
||||
*/
|
||||
public static final int POLARIS_LOAD_BALANCER_INTERCEPTOR_POST_PROCESSOR_ORDER = 0;
|
||||
|
||||
private BeanFactory factory;
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(@NonNull BeanFactory beanFactory) throws BeansException {
|
||||
this.factory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
|
||||
if (bean instanceof LoadBalancerInterceptor) {
|
||||
// Support rest template router.
|
||||
// Replaces the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor
|
||||
LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class);
|
||||
LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
|
||||
EnhancedPluginRunner pluginRunner = this.factory.getBean(EnhancedPluginRunner.class);
|
||||
return new PolarisLoadBalancerInterceptor(loadBalancerClient, requestFactory, pluginRunner);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return POLARIS_LOAD_BALANCER_INTERCEPTOR_POST_PROCESSOR_ORDER;
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.circuitbreaker.instrument.resttemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateWrapInterceptor;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* PolarisLoadBalancerInterceptor is a wrapper of LoadBalancerInterceptor.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
|
||||
|
||||
private final LoadBalancerClient loadBalancer;
|
||||
private final LoadBalancerRequestFactory requestFactory;
|
||||
|
||||
private final EnhancedPluginRunner enhancedPluginRunner;
|
||||
|
||||
public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory,
|
||||
EnhancedPluginRunner enhancedPluginRunner) {
|
||||
super(loadBalancer, requestFactory);
|
||||
this.loadBalancer = loadBalancer;
|
||||
this.requestFactory = requestFactory;
|
||||
this.enhancedPluginRunner = enhancedPluginRunner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
final URI originalUri = request.getURI();
|
||||
String peerServiceName = originalUri.getHost();
|
||||
Assert.state(peerServiceName != null,
|
||||
"Request URI does not contain a valid hostname: " + originalUri);
|
||||
|
||||
if (enhancedPluginRunner != null) {
|
||||
EnhancedRestTemplateWrapInterceptor enhancedRestTemplateWrapInterceptor = new EnhancedRestTemplateWrapInterceptor(enhancedPluginRunner, loadBalancer);
|
||||
return enhancedRestTemplateWrapInterceptor.intercept(request, peerServiceName, this.requestFactory.createRequest(request, body, execution));
|
||||
}
|
||||
else {
|
||||
return super.intercept(request, body, execution);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* 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.circuitbreaker.beanprocessor;
|
||||
|
||||
import com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate.PolarisLoadBalancerInterceptor;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Test for ${@link LoadBalancerInterceptorBeanPostProcessor}.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
class LoadBalancerInterceptorBeanPostProcessorTest {
|
||||
|
||||
@Mock
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Mock
|
||||
private LoadBalancerRequestFactory requestFactory;
|
||||
|
||||
@Mock
|
||||
private LoadBalancerClient loadBalancerClient;
|
||||
|
||||
@Mock
|
||||
private EnhancedPluginRunner pluginRunner;
|
||||
|
||||
private LoadBalancerInterceptorBeanPostProcessor processor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
processor = new LoadBalancerInterceptorBeanPostProcessor();
|
||||
processor.setBeanFactory(beanFactory);
|
||||
|
||||
// Setup mock behavior
|
||||
when(beanFactory.getBean(LoadBalancerRequestFactory.class)).thenReturn(requestFactory);
|
||||
when(beanFactory.getBean(LoadBalancerClient.class)).thenReturn(loadBalancerClient);
|
||||
when(beanFactory.getBean(EnhancedPluginRunner.class)).thenReturn(pluginRunner);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostProcessBeforeInitializationWithLoadBalancerInterceptor() {
|
||||
// Arrange
|
||||
LoadBalancerInterceptor originalInterceptor = mock(LoadBalancerInterceptor.class);
|
||||
String beanName = "testBean";
|
||||
|
||||
// Act
|
||||
Object result = processor.postProcessBeforeInitialization(originalInterceptor, beanName);
|
||||
|
||||
// Assert
|
||||
Assertions.assertInstanceOf(PolarisLoadBalancerInterceptor.class, result);
|
||||
verify(beanFactory).getBean(LoadBalancerRequestFactory.class);
|
||||
verify(beanFactory).getBean(LoadBalancerClient.class);
|
||||
verify(beanFactory).getBean(EnhancedPluginRunner.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostProcessBeforeInitializationWithNonLoadBalancerInterceptor() {
|
||||
// Arrange
|
||||
Object originalBean = new Object();
|
||||
String beanName = "testBean";
|
||||
|
||||
// Act
|
||||
Object result = processor.postProcessBeforeInitialization(originalBean, beanName);
|
||||
|
||||
// Assert
|
||||
Assertions.assertSame(originalBean, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrder() {
|
||||
// Act
|
||||
int order = processor.getOrder();
|
||||
|
||||
// Assert
|
||||
Assertions.assertEquals(LoadBalancerInterceptorBeanPostProcessor.POLARIS_LOAD_BALANCER_INTERCEPTOR_POST_PROCESSOR_ORDER, order);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetBeanFactory() {
|
||||
// Arrange
|
||||
BeanFactory newBeanFactory = mock(BeanFactory.class);
|
||||
LoadBalancerInterceptorBeanPostProcessor newProcessor = new LoadBalancerInterceptorBeanPostProcessor();
|
||||
|
||||
// Act
|
||||
newProcessor.setBeanFactory(newBeanFactory);
|
||||
|
||||
// Assert
|
||||
// Verify the bean factory is set by trying to process a bean
|
||||
LoadBalancerInterceptor interceptor = mock(LoadBalancerInterceptor.class);
|
||||
when(newBeanFactory.getBean(LoadBalancerRequestFactory.class)).thenReturn(requestFactory);
|
||||
when(newBeanFactory.getBean(LoadBalancerClient.class)).thenReturn(loadBalancerClient);
|
||||
when(newBeanFactory.getBean(EnhancedPluginRunner.class)).thenReturn(pluginRunner);
|
||||
|
||||
Object result = newProcessor.postProcessBeforeInitialization(interceptor, "testBean");
|
||||
Assertions.assertInstanceOf(PolarisLoadBalancerInterceptor.class, result);
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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.circuitbreaker.instrument.resttemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Test for ${@link PolarisLoadBalancerInterceptor}.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PolarisLoadBalancerInterceptorTest {
|
||||
|
||||
@Mock
|
||||
private LoadBalancerClient loadBalancer;
|
||||
|
||||
@Mock
|
||||
private LoadBalancerRequestFactory requestFactory;
|
||||
|
||||
@Mock
|
||||
private EnhancedPluginRunner enhancedPluginRunner;
|
||||
|
||||
@Mock
|
||||
private HttpRequest request;
|
||||
|
||||
@Mock
|
||||
private ClientHttpRequestExecution execution;
|
||||
|
||||
private PolarisLoadBalancerInterceptor interceptor;
|
||||
private byte[] body;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
body = "test body".getBytes();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInterceptWithEnhancedPlugin() throws IOException {
|
||||
// Arrange
|
||||
ClientHttpResponse mockResponse = mock(ClientHttpResponse.class);
|
||||
interceptor = new PolarisLoadBalancerInterceptor(loadBalancer, requestFactory, enhancedPluginRunner);
|
||||
URI uri = URI.create("http://test-service/path");
|
||||
when(request.getURI()).thenReturn(uri);
|
||||
when(loadBalancer.execute(any(), any())).thenReturn(mockResponse);
|
||||
|
||||
// Act
|
||||
ClientHttpResponse response = interceptor.intercept(request, body, execution);
|
||||
|
||||
// Assert
|
||||
Assertions.assertTrue(Objects.equals(mockResponse, response) || response instanceof PolarisCircuitBreakerHttpResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInterceptWithoutEnhancedPlugin() throws IOException {
|
||||
// Arrange
|
||||
ClientHttpResponse mockResponse = mock(ClientHttpResponse.class);
|
||||
interceptor = new PolarisLoadBalancerInterceptor(loadBalancer, requestFactory, null);
|
||||
URI uri = URI.create("http://test-service/path");
|
||||
when(request.getURI()).thenReturn(uri);
|
||||
when(loadBalancer.execute(any(), any())).thenReturn(mockResponse);
|
||||
|
||||
// Act
|
||||
ClientHttpResponse response = interceptor.intercept(request, body, execution);
|
||||
|
||||
// Assert
|
||||
Assertions.assertEquals(mockResponse, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInterceptWithInvalidUri() {
|
||||
// Arrange
|
||||
interceptor = new PolarisLoadBalancerInterceptor(loadBalancer, requestFactory, enhancedPluginRunner);
|
||||
when(request.getURI()).thenReturn(URI.create("http:///path")); // Invalid URI without host
|
||||
|
||||
// Act & Assert
|
||||
Exception exception = Assertions.assertThrows(IllegalStateException.class, () -> {
|
||||
interceptor.intercept(request, body, execution);
|
||||
});
|
||||
Assertions.assertTrue(exception.getMessage().contains("Request URI does not contain a valid hostname"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructor() {
|
||||
// Act
|
||||
interceptor = new PolarisLoadBalancerInterceptor(loadBalancer, requestFactory, enhancedPluginRunner);
|
||||
|
||||
// Assert
|
||||
Assertions.assertNotNull(interceptor);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue