refactor:refactor rpc enhancement.

pull/1080/head
Haotian Zhang 1 year ago
parent 0673da7818
commit 28a0a9fc63

@ -5,3 +5,4 @@
- feature: Enhance default configuration to support `application*.yaml` and `bootstrap*.yaml`.
- feat:adapt for nacos instance.
- Refactoring: Refactor Circuitbreaker ut.
- refactor:refactor rpc enhancement.

@ -89,7 +89,7 @@
<properties>
<!-- Project revision -->
<revision>1.12.0-Hoxton.SR12</revision>
<revision>1.12.0-Hoxton.SR12-SNAPSHOT</revision>
<!-- Spring Framework -->
<spring.framework.version>5.2.22.RELEASE</spring.framework.version>

@ -94,15 +94,15 @@ public class PolarisCircuitBreakerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean

@ -64,15 +64,15 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean

@ -19,15 +19,14 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,16 +35,22 @@ import org.springframework.cloud.client.ServiceInstance;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
/**
* ExceptionCircuitBreakerReporter.
*
* @author sean yu
*/
public class ExceptionCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class);
private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context);
this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI;
}
@ -56,20 +61,20 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance())
ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance())
.orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat(
ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),

@ -19,17 +19,16 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -38,17 +37,22 @@ import org.springframework.cloud.client.ServiceInstance;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
/**
* SuccessCircuitBreakerReporter.
*
* @author sean yu
*/
public class SuccessCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context);
this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI;
}
@ -59,20 +63,20 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance())
ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance())
.orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat(
ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),

@ -95,7 +95,7 @@ public class ExceptionCircuitBreakerReporterTest {
@Test
public void testType() {
assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION);
assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
@ -121,7 +121,7 @@ public class ExceptionCircuitBreakerReporterTest {
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
pluginContext.setThrowable(new RuntimeException());
exceptionCircuitBreakerReporter.run(pluginContext);

@ -40,6 +40,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -74,6 +75,12 @@ public class SuccessCircuitBreakerReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -94,7 +101,7 @@ public class SuccessCircuitBreakerReporterTest {
@Test
public void testType() {
assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.POST);
assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
@ -120,7 +127,7 @@ public class SuccessCircuitBreakerReporterTest {
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
successCircuitBreakerReporter.run(pluginContext);
successCircuitBreakerReporter.getOrder();

@ -45,6 +45,11 @@ public class PolarisDiscoveryProperties {
@Value("${spring.cloud.polaris.discovery.service:${spring.cloud.polaris.service:${spring.application.name:}}}")
private String service;
/**
* Service instance id.
*/
private String instanceId;
/**
* The polaris authentication token.
*/
@ -96,6 +101,14 @@ public class PolarisDiscoveryProperties {
*/
private Long serviceListRefreshInterval = 60000L;
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getNamespace() {
return namespace;
}
@ -204,6 +217,7 @@ public class PolarisDiscoveryProperties {
return "PolarisDiscoveryProperties{" +
"namespace='" + namespace + '\'' +
", service='" + service + '\'' +
", instanceId='" + instanceId + '\'' +
", token='" + token + '\'' +
", weight=" + weight +
", version='" + version + '\'' +

@ -17,6 +17,9 @@
package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,15 +35,21 @@ import org.springframework.util.StringUtils;
*/
public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistration<PolarisRegistration> {
private static final Logger LOG = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class);
private static final Logger log = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class);
private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<PolarisRegistration> serviceRegistry,
private final AssemblyAPI assemblyAPI;
public PolarisAutoServiceRegistration(
ServiceRegistry<PolarisRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) {
PolarisRegistration registration,
AssemblyAPI assemblyAPI
) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
this.assemblyAPI = assemblyAPI;
}
@Override
@ -56,9 +65,12 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
@Override
protected void register() {
if (!this.registration.isRegisterEnabled()) {
LOG.debug("Registration disabled.");
log.debug("Registration disabled.");
return;
}
if (assemblyAPI != null) {
assemblyAPI.initService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
}
super.register();
}

@ -113,6 +113,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
instanceRegisterRequest.setMetadata(registration.getMetadata());
instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion());
instanceRegisterRequest.setInstanceId(polarisDiscoveryProperties.getInstanceId());
try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
InstanceRegisterResponse instanceRegisterResponse;

@ -26,6 +26,7 @@ import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired;
@ -50,8 +51,7 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties
@ConditionalOnPolarisRegisterEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class,
PolarisDiscoveryAutoConfiguration.class})
public class PolarisServiceRegistryAutoConfiguration {
@ -82,8 +82,10 @@ public class PolarisServiceRegistryAutoConfiguration {
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(
PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
PolarisRegistration registration,
@Autowired(required = false) AssemblyAPI assemblyAPI
) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration, assemblyAPI);
}
@Bean

@ -85,10 +85,15 @@ public class PolarisDiscoveryPropertiesTest {
polarisDiscoveryProperties.setServiceListRefreshInterval(1000L);
assertThat(polarisDiscoveryProperties.getServiceListRefreshInterval()).isEqualTo(1000L);
// InstanceId
polarisDiscoveryProperties.setInstanceId("test-ins-id");
assertThat(polarisDiscoveryProperties.getInstanceId()).isEqualTo("test-ins-id");
assertThat(polarisDiscoveryProperties.toString())
.isEqualTo("PolarisDiscoveryProperties{"
+ "namespace='Test'"
+ ", service='java_provider_test'"
+ ", instanceId='test-ins-id'"
+ ", token='19485a7674294e3c88dba293373c1534'"
+ ", weight=10, version='1.0.0'"
+ ", protocol='HTTP'"

@ -75,7 +75,7 @@ public class PolarisAutoServiceRegistrationTest {
doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class));
polarisAutoServiceRegistration =
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration);
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration, null);
doReturn(environment).when(applicationContext).getEnvironment();
polarisAutoServiceRegistration.setApplicationContext(applicationContext);

@ -48,11 +48,6 @@ public class MetadataContext {
*/
public static final String FRAGMENT_DISPOSABLE = "disposable";
/**
* load balancer context.
*/
public static final String FRAGMENT_LOAD_BALANCER = "loadbalancer";
/**
* upstream disposable Context.
*/
@ -115,8 +110,12 @@ public class MetadataContext {
private final Map<String, Map<String, String>> fragmentContexts;
private final Map<String, Object> loadbalancerMetadata;
public MetadataContext() {
this.fragmentContexts = new ConcurrentHashMap<>();
this.loadbalancerMetadata = new ConcurrentHashMap<>();
}
public Map<String, String> getDisposableMetadata() {
@ -148,8 +147,8 @@ public class MetadataContext {
return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV);
}
public Map<String, String> getLoadbalancerMetadata() {
return this.getFragmentContext(FRAGMENT_LOAD_BALANCER);
public Map<String, Object> getLoadbalancerMetadata() {
return this.loadbalancerMetadata;
}
public void setTransitiveMetadata(Map<String, String> transitiveMetadata) {
@ -172,8 +171,8 @@ public class MetadataContext {
this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
}
public void setLoadbalancer(String key, String value) {
this.putContext(FRAGMENT_LOAD_BALANCER, key, value);
public void setLoadbalancer(String key, Object value) {
this.loadbalancerMetadata.put(key, value);
}
public Map<String, String> getFragmentContext(String fragment) {

@ -70,7 +70,7 @@
</developers>
<properties>
<revision>1.12.0-Hoxton.SR12</revision>
<revision>1.12.0-Hoxton.SR12-SNAPSHOT</revision>
<!-- Dependencies -->
<polaris.version>1.13.0</polaris.version>

@ -110,6 +110,11 @@
<groupId>com.tencent.polaris</groupId>
<artifactId>loadbalancer-ringhash</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-assembly-factory</artifactId>
</dependency>
<!-- Polaris dependencies end -->
<dependency>

@ -27,6 +27,8 @@ import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.factory.AssemblyAPIFactory;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.factory.api.RouterAPIFactory;
@ -73,6 +75,11 @@ public class PolarisContextAutoConfiguration {
return RouterAPIFactory.createRouterAPIByContext(polarisContext);
}
@Bean
public AssemblyAPI assemblyAPI(SDKContext polarisContext) throws PolarisException {
return AssemblyAPIFactory.createAssemblyAPIByContext(polarisContext);
}
@Bean
@ConditionalOnMissingBean
public ModifyAddress polarisConfigModifier(PolarisContextProperties properties) {

@ -17,7 +17,7 @@
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
<artifactId>spring-cloud-tencent-rpc-enhancement</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->

@ -36,7 +36,7 @@ public final class PolarisLoadBalancerRingHashKeyProvider {
}
static String getHashKey() {
return MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY);
return (String) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY);
}
}

@ -17,15 +17,24 @@
package com.tencent.cloud.polaris.loadbalancer.config;
import java.util.ArrayList;
import java.util.List;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
/**
* Auto-configuration Ribbon for Polaris.
@ -44,4 +53,24 @@ public class PolarisLoadBalancerAutoConfiguration {
public PolarisLoadBalancerProperties polarisLoadBalancerProperties() {
return new PolarisLoadBalancerProperties();
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(@Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
// LoadBalancerInterceptor must invoke before EnhancedRestTemplateInterceptor
if (loadBalancerInterceptor != null) {
int addIndex = list.size();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EnhancedRestTemplateInterceptor) {
addIndex = i;
}
}
list.add(addIndex, loadBalancerInterceptor);
}
restTemplate.setInterceptors(list);
};
}
}

@ -24,20 +24,22 @@ import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor;
import com.tencent.cloud.rpc.enhancement.filter.EnhancedReactiveFilter;
import com.tencent.cloud.rpc.enhancement.filter.EnhancedServletFilter;
import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.cloud.rpc.enhancement.resttemplate.BlockingLoadBalancerClientAspect;
import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
import com.tencent.cloud.rpc.enhancement.resttemplate.RibbonLoadBalancerClientAspect;
import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer;
import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter;
import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientReporter;
import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientExchangeFilterFunction;
import com.tencent.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer;
import com.tencent.cloud.rpc.enhancement.webclient.RibbonLoadBalancerClientAspect;
import com.tencent.cloud.rpc.enhancement.zuul.EnhancedErrorZuulFilter;
import com.tencent.cloud.rpc.enhancement.zuul.EnhancedPostZuulFilter;
import com.tencent.cloud.rpc.enhancement.zuul.EnhancedPreZuulFilter;
import com.tencent.cloud.rpc.enhancement.zuul.EnhancedRouteZuulFilter;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
@ -49,16 +51,26 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import static javax.servlet.DispatcherType.ASYNC;
import static javax.servlet.DispatcherType.ERROR;
import static javax.servlet.DispatcherType.FORWARD;
import static javax.servlet.DispatcherType.INCLUDE;
import static javax.servlet.DispatcherType.REQUEST;
/**
* Auto Configuration for Polaris {@link feign.Feign} OR {@link RestTemplate} which can automatically bring in the call
* results for reporting.
@ -73,23 +85,55 @@ import org.springframework.web.reactive.function.client.WebClient;
public class RpcEnhancementAutoConfiguration {
@Bean
@Lazy
public EnhancedPluginRunner enhancedFeignPluginRunner(
@Autowired(required = false) List<EnhancedPlugin> enhancedPlugins) {
return new DefaultEnhancedPluginRunner(enhancedPlugins);
@Autowired(required = false) List<EnhancedPlugin> enhancedPlugins,
@Autowired(required = false) Registration registration,
SDKContext sdkContext) {
return new DefaultEnhancedPluginRunner(enhancedPlugins, registration, sdkContext);
}
@Bean
public SuccessPolarisReporter successPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) {
return new SuccessPolarisReporter(properties, context, consumerAPI);
return new SuccessPolarisReporter(properties, consumerAPI);
}
@Bean
public ExceptionPolarisReporter exceptionPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) {
return new ExceptionPolarisReporter(properties, context, consumerAPI);
return new ExceptionPolarisReporter(properties, consumerAPI);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
protected static class RpcEnhancementServletFilterConfig {
@Bean
public FilterRegistrationBean<EnhancedServletFilter> enhancedServletFilterRegistrationBean(
EnhancedServletFilter enhancedServletFilter) {
FilterRegistrationBean<EnhancedServletFilter> filterRegistrationBean =
new FilterRegistrationBean<>(enhancedServletFilter);
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST);
filterRegistrationBean.setOrder(enhancedServletFilter.getClass().getAnnotation(Order.class).value());
return filterRegistrationBean;
}
@Bean
public EnhancedServletFilter enhancedServletFilter(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedServletFilter(pluginRunner);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
protected static class RpcEnhancementReactiveFilterConfig {
@Bean
public EnhancedReactiveFilter enhancedReactiveFilter(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedReactiveFilter(pluginRunner);
}
}
/**
@ -141,16 +185,9 @@ public class RpcEnhancementAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient"})
public BlockingLoadBalancerClientAspect blockingLoadBalancerClientAspect() {
return new BlockingLoadBalancerClientAspect();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient"})
public RibbonLoadBalancerClientAspect ribbonLoadBalancerClientAspect() {
return new RibbonLoadBalancerClientAspect();
@ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"})
public PolarisLoadBalancerRequestTransformer polarisLoadBalancerRequestTransformer() {
return new PolarisLoadBalancerRequestTransformer();
}
}
@ -166,12 +203,12 @@ public class RpcEnhancementAutoConfiguration {
private List<WebClient.Builder> webClientBuilder = Collections.emptyList();
@Bean
public EnhancedWebClientReporter exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedWebClientReporter(pluginRunner);
public EnhancedWebClientExchangeFilterFunction exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedWebClientExchangeFilterFunction(pluginRunner);
}
@Bean
public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientReporter reporter) {
public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientExchangeFilterFunction reporter) {
return () -> webClientBuilder.forEach(webClient -> {
webClient.filter(reporter);
});
@ -184,6 +221,12 @@ public class RpcEnhancementAutoConfiguration {
return new PolarisLoadBalancerClientRequestTransformer();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient"})
public RibbonLoadBalancerClientAspect ribbonLoadBalancerClientAspect() {
return new RibbonLoadBalancerClientAspect();
}
}
/**
@ -211,8 +254,8 @@ public class RpcEnhancementAutoConfiguration {
@ConditionalOnClass(name = "com.netflix.zuul.http.ZuulServlet")
protected static class PolarisCircuitBreakerZuulFilterConfig {
@Bean
public EnhancedPreZuulFilter enhancedZuulPreFilter(@Lazy EnhancedPluginRunner pluginRunner, Environment environment) {
return new EnhancedPreZuulFilter(pluginRunner, environment);
public EnhancedRouteZuulFilter enhancedZuulRouteFilter(@Lazy EnhancedPluginRunner pluginRunner, Environment environment) {
return new EnhancedRouteZuulFilter(pluginRunner, environment);
}
@Bean

@ -23,6 +23,7 @@ import java.util.ArrayList;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import feign.Client;
@ -34,10 +35,6 @@ import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static feign.Util.checkNotNull;
/**
@ -66,13 +63,19 @@ public class EnhancedFeignClient implements Client {
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders)
.httpMethod(HttpMethod.resolve(request.httpMethod().name()))
.httpMethod(HttpMethod.valueOf(request.httpMethod().name()))
.url(url)
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(request.requestTemplate().feignTarget()
.name(), url.getHost(), url.getPort(), url.getScheme().equals("https"));
enhancedPluginContext.setTargetServiceInstance(serviceInstance);
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
Response response = delegate.execute(request, options);
@ -87,24 +90,20 @@ public class EnhancedFeignClient implements Client {
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(request.requestTemplate().feignTarget()
.name(), url.getHost(), url.getPort(), url.getScheme().equals("https"));
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response;
}
catch (IOException origin) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(origin);
// Run exception enhanced feign plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw origin;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
}
}

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement.filter;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
/**
* EnhancedReactiveFilter.
*
* @author sean yu
*/
public class EnhancedReactiveFilter implements WebFilter, Ordered {
private final EnhancedPluginRunner pluginRunner;
public EnhancedReactiveFilter(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(exchange.getRequest().getHeaders())
.httpMethod(exchange.getRequest().getMethod())
.url(exchange.getRequest().getURI())
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSuccess(v -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(exchange.getResponse().getRawStatusCode())
.httpHeaders(exchange.getResponse().getHeaders())
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext);
})
.doOnError(e -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext);
});
}
@Override
public int getOrder() {
return MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1;
}
}

@ -0,0 +1,116 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement.filter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* EnhancedServletFilter.
*
* @author sean yu
*/
@Order(MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1)
public class EnhancedServletFilter extends OncePerRequestFilter {
private final EnhancedPluginRunner pluginRunner;
public EnhancedServletFilter(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders();
Enumeration<String> requestHeaderNames = request.getHeaderNames();
if (requestHeaderNames != null) {
while (requestHeaderNames.hasMoreElements()) {
String requestHeaderName = requestHeaderNames.nextElement();
requestHeaders.addAll(requestHeaderName, Collections.list(request.getHeaders(requestHeaderName)));
}
}
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders)
.httpMethod(HttpMethod.valueOf(request.getMethod()))
.url(URI.create(request.getRequestURL().toString()))
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
filterChain.doFilter(request, response);
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
HttpHeaders responseHeaders = new HttpHeaders();
Collection<String> responseHeaderNames = response.getHeaderNames();
if (responseHeaderNames != null) {
for (String responseHeaderName : responseHeaderNames) {
responseHeaders.addAll(responseHeaderName, new ArrayList<>(response.getHeaders(responseHeaderName)));
}
}
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(response.getStatus())
.httpHeaders(responseHeaders)
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext);
}
catch (ServletException | IOException e) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext);
throw e;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext);
}
}
}

@ -23,7 +23,12 @@ import java.util.List;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.util.CollectionUtils;
/**
@ -33,13 +38,28 @@ import org.springframework.util.CollectionUtils;
*/
public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
private final Multimap<String, EnhancedPlugin> pluginMap = ArrayListMultimap.create();
private final Multimap<EnhancedPluginType, EnhancedPlugin> pluginMap = ArrayListMultimap.create();
public DefaultEnhancedPluginRunner(List<EnhancedPlugin> enhancedPlugins) {
private final ServiceInstance localServiceInstance;
public DefaultEnhancedPluginRunner(
List<EnhancedPlugin> enhancedPlugins,
Registration registration,
SDKContext sdkContext
) {
if (!CollectionUtils.isEmpty(enhancedPlugins)) {
enhancedPlugins.stream()
.sorted(Comparator.comparing(EnhancedPlugin::getOrder))
.forEach(plugin -> pluginMap.put(plugin.getType().name(), plugin));
.forEach(plugin -> pluginMap.put(plugin.getType(), plugin));
}
if (registration != null) {
localServiceInstance = registration;
}
else {
DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();
defaultServiceInstance.setServiceId(MetadataContext.LOCAL_SERVICE);
defaultServiceInstance.setHost(sdkContext.getConfig().getGlobal().getAPI().getBindIP());
localServiceInstance = defaultServiceInstance;
}
}
@ -51,7 +71,7 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
*/
@Override
public void run(EnhancedPluginType pluginType, EnhancedPluginContext context) {
for (EnhancedPlugin plugin : pluginMap.get(pluginType.name())) {
for (EnhancedPlugin plugin : pluginMap.get(pluginType)) {
try {
plugin.run(context);
}
@ -60,4 +80,10 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
}
}
}
@Override
public ServiceInstance getLocalServiceInstance() {
return this.localServiceInstance;
}
}

@ -35,7 +35,12 @@ public class EnhancedPluginContext {
private long delay;
private ServiceInstance serviceInstance;
private ServiceInstance localServiceInstance;
/**
* targetServiceInstance only exist in a client runner type.
*/
private ServiceInstance targetServiceInstance;
public EnhancedRequestContext getRequest() {
return request;
@ -69,12 +74,20 @@ public class EnhancedPluginContext {
this.delay = delay;
}
public ServiceInstance getServiceInstance() {
return serviceInstance;
public ServiceInstance getLocalServiceInstance() {
return localServiceInstance;
}
public void setLocalServiceInstance(ServiceInstance localServiceInstance) {
this.localServiceInstance = localServiceInstance;
}
public void setServiceInstance(ServiceInstance serviceInstance) {
this.serviceInstance = serviceInstance;
public ServiceInstance getTargetServiceInstance() {
return targetServiceInstance;
}
public void setTargetServiceInstance(ServiceInstance targetServiceInstance) {
this.targetServiceInstance = targetServiceInstance;
}
@Override
@ -84,7 +97,9 @@ public class EnhancedPluginContext {
", response=" + response +
", throwable=" + throwable +
", delay=" + delay +
", serviceInstance=" + serviceInstance +
", localServiceInstance=" + localServiceInstance +
", targetServiceInstance=" + targetServiceInstance +
'}';
}
}

@ -18,6 +18,8 @@
package com.tencent.cloud.rpc.enhancement.plugin;
import org.springframework.cloud.client.ServiceInstance;
/**
* Plugin runner.
*
@ -32,4 +34,7 @@ public interface EnhancedPluginRunner {
* @param context context in enhanced feign client.
*/
void run(EnhancedPluginType pluginType, EnhancedPluginContext context);
ServiceInstance getLocalServiceInstance();
}

@ -22,25 +22,52 @@ package com.tencent.cloud.rpc.enhancement.plugin;
*
* @author Haotian Zhang
*/
public enum EnhancedPluginType {
/**
* Pre feign plugin.
*/
PRE,
/**
* Post feign plugin.
*/
POST,
/**
* Exception feign plugin.
*/
EXCEPTION,
/**
* Finally feign plugin.
*/
FINALLY
public interface EnhancedPluginType {
enum Client implements EnhancedPluginType {
/**
* Pre Client plugin.
*/
PRE,
/**
* Post Client plugin.
*/
POST,
/**
* Exception Client plugin.
*/
EXCEPTION,
/**
* Finally Client plugin.
*/
FINALLY
}
enum Server implements EnhancedPluginType {
/**
* Pre Server plugin.
*/
PRE,
/**
* Post Server plugin.
*/
POST,
/**
* Exception Server plugin.
*/
EXCEPTION,
/**
* Finally Server plugin.
*/
FINALLY
}
}

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement;
package com.tencent.cloud.rpc.enhancement.plugin;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
@ -24,12 +24,18 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.RequestLabelUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
@ -39,11 +45,11 @@ import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
@ -63,30 +69,21 @@ import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE;
import static org.springframework.http.HttpStatus.VARIANT_ALSO_NEGOTIATES;
/**
* Abstract Polaris Reporter Adapter .
* Abstract Polaris Plugin Adapter .
*
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-11
*/
public abstract class AbstractPolarisReporterAdapter {
private static final Logger LOG = LoggerFactory.getLogger(AbstractPolarisReporterAdapter.class);
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
public final class PolarisEnhancedPluginUtils {
protected final RpcEnhancementReporterProperties reportProperties;
private PolarisEnhancedPluginUtils() {
protected final SDKContext context;
/**
* Constructor With {@link RpcEnhancementReporterProperties} .
*
* @param reportProperties instance of {@link RpcEnhancementReporterProperties}.
*/
protected AbstractPolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) {
this.reportProperties = reportProperties;
this.context = context;
}
private static final Logger LOG = LoggerFactory.getLogger(PolarisEnhancedPluginUtils.class);
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
/**
* createServiceCallResult.
* @param calleeServiceName will pick up url host when null
@ -100,7 +97,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception
* @return ServiceCallResult
*/
public ServiceCallResult createServiceCallResult(
public static ServiceCallResult createServiceCallResult(String callerHost,
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, HttpHeaders requestHeaders, @Nullable HttpHeaders responseHeaders,
@Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
@ -112,11 +109,11 @@ public abstract class AbstractPolarisReporterAdapter {
resultRequest.setRetCode(statusCode == null ? -1 : statusCode);
resultRequest.setDelay(delay);
resultRequest.setCallerService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
resultRequest.setCallerIp(this.context.getConfig().getGlobal().getAPI().getBindIP());
resultRequest.setCallerIp(callerHost);
resultRequest.setHost(StringUtils.isBlank(calleeHost) ? uri.getHost() : calleeHost);
resultRequest.setPort(calleePort == null ? getPort(uri) : calleePort);
resultRequest.setLabels(getLabels(requestHeaders));
resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, getDefaultRetStatus(statusCode, exception)));
resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, statusCode, exception));
resultRequest.setRuleName(getActiveRuleNameFromRequest(responseHeaders));
return resultRequest;
}
@ -132,7 +129,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception
* @return ResourceStat
*/
public ResourceStat createInstanceResourceStat(
public static ResourceStat createInstanceResourceStat(
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
ServiceKey calleeServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName);
@ -165,42 +162,40 @@ public abstract class AbstractPolarisReporterAdapter {
* @param httpStatus request http status code
* @return true , otherwise return false .
*/
protected boolean apply(@Nullable HttpStatus httpStatus) {
static boolean apply(@Nullable HttpStatus httpStatus) {
if (Objects.isNull(httpStatus)) {
return false;
}
else {
// statuses > series
List<HttpStatus> status = reportProperties.getStatuses();
if (status.isEmpty()) {
List<HttpStatus.Series> series = reportProperties.getSeries();
// Check INTERNAL_SERVER_ERROR (500) status.
if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) {
return false;
}
if (series.isEmpty()) {
return HTTP_STATUSES.contains(httpStatus);
}
else {
try {
return series.contains(HttpStatus.Series.valueOf(httpStatus));
}
catch (Exception e) {
LOG.warn("Decode http status failed.", e);
}
}
RpcEnhancementReporterProperties reportProperties;
try {
reportProperties = ApplicationContextAwareUtils.getApplicationContext().getBean(RpcEnhancementReporterProperties.class);
}
catch (BeansException e) {
LOG.error("get RpcEnhancementReporterProperties bean err", e);
reportProperties = new RpcEnhancementReporterProperties();
}
// statuses > series
List<HttpStatus> status = reportProperties.getStatuses();
if (status.isEmpty()) {
List<HttpStatus.Series> series = reportProperties.getSeries();
// Check INTERNAL_SERVER_ERROR (500) status.
if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) {
return false;
}
else {
// Use the user-specified fuse status code.
return status.contains(httpStatus);
if (series.isEmpty()) {
return HTTP_STATUSES.contains(httpStatus);
}
return series.contains(httpStatus.series());
}
// DEFAULT RETURN FALSE.
return false;
// Use the user-specified fuse status code.
return status.contains(httpStatus);
}
public static RetStatus getRetStatusFromRequest(HttpHeaders headers, Integer statusCode, Throwable exception) {
return getRetStatusFromRequest(headers, getDefaultRetStatus(statusCode, exception));
}
protected RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) {
static RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_CALLEE_RET_STATUS)) {
List<String> values = headers.get(HeaderConstant.INTERNAL_CALLEE_RET_STATUS);
if (CollectionUtils.isNotEmpty(values)) {
@ -216,7 +211,7 @@ public abstract class AbstractPolarisReporterAdapter {
return defaultVal;
}
protected String getActiveRuleNameFromRequest(HttpHeaders headers) {
static String getActiveRuleNameFromRequest(HttpHeaders headers) {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) {
Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME);
if (CollectionUtils.isNotEmpty(values)) {
@ -226,7 +221,7 @@ public abstract class AbstractPolarisReporterAdapter {
return "";
}
private RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) {
private static RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) {
RetStatus retStatus = RetStatus.RetSuccess;
if (exception != null) {
retStatus = RetStatus.RetFail;
@ -240,12 +235,12 @@ public abstract class AbstractPolarisReporterAdapter {
return retStatus;
}
private int getPort(URI uri) {
private static int getPort(URI uri) {
// -1 means access directly by url, and use http default port number 80
return uri.getPort() == -1 ? 80 : uri.getPort();
}
private String getLabels(HttpHeaders headers) {
private static String getLabels(HttpHeaders headers) {
if (headers != null) {
Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER);
if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) {
@ -262,5 +257,27 @@ public abstract class AbstractPolarisReporterAdapter {
return null;
}
public static Map<String, String> getLabelMap(HttpHeaders headers) {
if (headers != null) {
Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER);
if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) {
String label = labels.iterator().next();
try {
label = URLDecoder.decode(label, UTF_8);
}
catch (UnsupportedEncodingException e) {
LOG.error("unsupported charset exception " + UTF_8, e);
}
try {
return new ObjectMapper().readValue(label, new TypeReference<HashMap<String, String>>() { });
}
catch (JsonProcessingException e) {
LOG.error("parse label map exception", e);
}
}
}
return null;
}
}

@ -20,15 +20,14 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -42,16 +41,17 @@ import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.Clien
*
* @author Haotian Zhang
*/
public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
public class ExceptionPolarisReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionPolarisReporter.class);
private final ConsumerAPI consumerAPI;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reporterProperties,
SDKContext context,
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) {
super(reporterProperties, context);
this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI;
}
@ -62,23 +62,24 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance())
.orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
callerServiceInstance.getHost(),
calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(),
request.getHttpHeaders(),
null,
@ -88,8 +89,7 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
);
LOG.debug("Will report ServiceCallResult of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.",
resultRequest.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl()
.getPath(), context.getThrowable().getMessage(), context.getDelay());
resultRequest.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl().getPath(), context.getThrowable().getMessage(), context.getDelay());
consumerAPI.updateServiceCallResult(resultRequest);

@ -19,16 +19,15 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -42,16 +41,17 @@ import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.Clien
*
* @author Haotian Zhang
*/
public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
public class SuccessPolarisReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final ConsumerAPI consumerAPI;
public SuccessPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
private final RpcEnhancementReporterProperties reportProperties;
public SuccessPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) {
super(properties, context);
this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI;
}
@ -62,24 +62,25 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance())
.orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
callerServiceInstance.getHost(),
calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(),
request.getHttpHeaders(),
response.getHttpHeaders(),
@ -89,8 +90,7 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
);
LOG.debug("Will report ServiceCallResult of {}. Request=[{} {}]. Response=[{}]. Delay=[{}]ms.",
resultRequest.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl()
.getPath(), response.getHttpStatus(), context.getDelay());
resultRequest.getRetStatus().name(), request.getHttpMethod().name(), request.getUrl().getPath(), response.getHttpStatus(), context.getDelay());
consumerAPI.updateServiceCallResult(resultRequest);

@ -1,43 +0,0 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement.resttemplate;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
/**
* Intercept for BlockingLoadBalancerClient, put host and port to thread local.
*
* @author lepdou 2022-09-05
*/
@Aspect
public class BlockingLoadBalancerClientAspect {
@Pointcut("execution(public * org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.reconstructURI(..)) ")
public void pointcut() {
}
@Around("pointcut()")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint);
return joinPoint.proceed();
}
}

@ -18,25 +18,21 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import java.io.IOException;
import java.util.Map;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedRestTemplateInterceptor.
@ -63,8 +59,13 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
ClientHttpResponse response = execution.execute(request, body);
@ -76,29 +77,20 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
Map<String, String> loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(request.getURI().getHost());
serviceInstance.setHost(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST));
if (loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT) != null) {
serviceInstance.setPort(Integer.parseInt(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT)));
}
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response;
}
catch (IOException e) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw e;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
}

@ -17,28 +17,36 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer;
import org.springframework.http.HttpRequest;
/**
* Extract load balancer result from {@link LoadBalancerClient} and put to MetadataContext.
* @author lepdou 2022-09-06
* PolarisLoadBalancerRequestTransformer.
*
* @author sean yu
*/
public final class LoadBalancerClientAspectUtils {
public class PolarisLoadBalancerRequestTransformer implements LoadBalancerRequestTransformer {
private LoadBalancerClientAspectUtils() {
}
/**
* LOAD_BALANCER_SERVICE_INSTANCE MetadataContext key.
*/
public static final String LOAD_BALANCER_SERVICE_INSTANCE = "LOAD_BALANCER_SERVICE_INSTANCE";
public static void extractLoadBalancerResult(ProceedingJoinPoint joinPoint) {
Object server = joinPoint.getArgs()[0];
if (server instanceof ServiceInstance) {
ServiceInstance instance = (ServiceInstance) server;
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST, instance.getHost());
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT, String.valueOf(instance.getPort()));
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override
public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
}
return request;
}
}

@ -21,6 +21,7 @@ import java.net.URI;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
@ -33,10 +34,6 @@ import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
@ -64,8 +61,15 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
// enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Response<ServiceInstance> serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR);
// if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) {
// ServiceInstance instance = serviceInstanceResponse.getServer();
// enhancedPluginContext.setTargetServiceInstance(instance);
// }
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
@ -80,7 +84,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
serviceInstance.setHost(uri.getHost());
serviceInstance.setPort(uri.getPort());
}
enhancedPluginContext.setServiceInstance(serviceInstance);
enhancedPluginContext.setTargetServiceInstance(serviceInstance);
})
.doOnSuccess(v -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
@ -91,18 +95,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
})
.doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
});
}

@ -17,35 +17,31 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import java.util.Map;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedWebClientReporter.
* EnhancedWebClientExchangeFilterFunction.
*
* @author sean yu
*/
public class EnhancedWebClientReporter implements ExchangeFilterFunction {
public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFunction {
private final EnhancedPluginRunner pluginRunner;
public EnhancedWebClientReporter(EnhancedPluginRunner pluginRunner) {
public EnhancedWebClientExchangeFilterFunction(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@ -60,38 +56,37 @@ public class EnhancedWebClientReporter implements ExchangeFilterFunction {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis();
return next.exchange(request)
.doOnSubscribe(subscription -> {
Map<String, String> loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID));
serviceInstance.setHost(request.url().getHost());
serviceInstance.setPort(request.url().getPort());
enhancedPluginContext.setServiceInstance(serviceInstance);
})
.doOnSuccess(response -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(response.rawStatusCode())
.httpStatus(response.statusCode().value())
.httpHeaders(response.headers().asHttpHeaders())
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
})
.doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
});
}
}

@ -17,13 +17,14 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerClientRequestTransformer;
import org.springframework.web.reactive.function.client.ClientRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* PolarisLoadBalancerClientRequestTransformer.
*
@ -31,10 +32,16 @@ import org.springframework.web.reactive.function.client.ClientRequest;
*/
public class PolarisLoadBalancerClientRequestTransformer implements LoadBalancerClientRequestTransformer {
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override
public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID, instance.getServiceId());
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
}
return request;
}

@ -15,13 +15,16 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement.resttemplate;
package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* Intercept for RibbonLoadBalancerClient, put host and port to thread local.
*
@ -30,14 +33,17 @@ import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class RibbonLoadBalancerClientAspect {
@Pointcut("execution(public * org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.reconstructURI(..))")
@Pointcut("execution(public * org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(..))")
public void pointcut() {
}
@Around("pointcut()")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint);
return joinPoint.proceed();
Object result = joinPoint.proceed();
if (result != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, result);
}
return result;
}
}

@ -24,22 +24,18 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.util.ZuulFilterUtils;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.netflix.ribbon.apache.RibbonApacheHttpResponse;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import static com.tencent.cloud.common.constant.ContextConstant.Zuul.POLARIS_PRE_ROUTE_TIME;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ERROR_TYPE;
/**
@ -90,13 +86,9 @@ public class EnhancedErrorZuulFilter extends ZuulFilter {
enhancedPluginContext = (EnhancedPluginContext) enhancedPluginContextObj;
}
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
Object ribbonResponseObj = context.get("ribbonResponse");
Object startTimeMilliObject = context.get(POLARIS_PRE_ROUTE_TIME);
Throwable throwable = context.getThrowable();
RibbonApacheHttpResponse ribbonResponse;
if (throwable != null && ribbonResponseObj != null && ribbonResponseObj instanceof RibbonApacheHttpResponse
&& startTimeMilliObject != null && startTimeMilliObject instanceof Long) {
if (throwable != null && startTimeMilliObject != null && startTimeMilliObject instanceof Long) {
HttpHeaders responseHeaders = new HttpHeaders();
Collection<String> names = context.getResponse().getHeaderNames();
for (String name : names) {
@ -110,17 +102,12 @@ public class EnhancedErrorZuulFilter extends ZuulFilter {
Long startTimeMilli = (Long) startTimeMilliObject;
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTimeMilli);
enhancedPluginContext.setThrowable(throwable);
ribbonResponse = (RibbonApacheHttpResponse) ribbonResponseObj;
serviceInstance.setServiceId(ZuulFilterUtils.getServiceId(context));
serviceInstance.setHost(ribbonResponse.getRequestedURI().getHost());
serviceInstance.setPort(ribbonResponse.getRequestedURI().getPort());
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
return null;
}

@ -24,22 +24,18 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.util.ZuulFilterUtils;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.netflix.ribbon.apache.RibbonApacheHttpResponse;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import static com.tencent.cloud.common.constant.ContextConstant.Zuul.POLARIS_PRE_ROUTE_TIME;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;
@ -89,12 +85,8 @@ public class EnhancedPostZuulFilter extends ZuulFilter {
enhancedPluginContext = (EnhancedPluginContext) enhancedPluginContextObj;
}
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
Object ribbonResponseObj = context.get("ribbonResponse");
Object startTimeMilliObject = context.get(POLARIS_PRE_ROUTE_TIME);
RibbonApacheHttpResponse ribbonResponse;
if (ribbonResponseObj != null && ribbonResponseObj instanceof RibbonApacheHttpResponse
&& startTimeMilliObject != null && startTimeMilliObject instanceof Long) {
if (startTimeMilliObject instanceof Long) {
HttpHeaders responseHeaders = new HttpHeaders();
Collection<String> names = context.getResponse().getHeaderNames();
for (String name : names) {
@ -107,17 +99,12 @@ public class EnhancedPostZuulFilter extends ZuulFilter {
enhancedPluginContext.setResponse(enhancedResponseContext);
Long startTimeMilli = (Long) startTimeMilliObject;
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTimeMilli);
ribbonResponse = (RibbonApacheHttpResponse) ribbonResponseObj;
serviceInstance.setServiceId(ZuulFilterUtils.getServiceId(context));
serviceInstance.setHost(ribbonResponse.getRequestedURI().getHost());
serviceInstance.setPort(ribbonResponse.getRequestedURI().getPort());
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
return null;
}

@ -29,46 +29,48 @@ import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.util.ZuulFilterUtils;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.netflix.ribbon.apache.RibbonApacheHttpResponse;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.StringUtils;
import static com.tencent.cloud.common.constant.ContextConstant.Zuul.POLARIS_PRE_ROUTE_TIME;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.RIBBON_ROUTING_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
/**
* Polaris circuit breaker implement in Zuul.
*
* @author Haotian Zhang
*/
public class EnhancedPreZuulFilter extends ZuulFilter {
public class EnhancedRouteZuulFilter extends ZuulFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(EnhancedPreZuulFilter.class);
private static final Logger LOGGER = LoggerFactory.getLogger(EnhancedRouteZuulFilter.class);
private final EnhancedPluginRunner pluginRunner;
private final Environment environment;
public EnhancedPreZuulFilter(EnhancedPluginRunner pluginRunner, Environment environment) {
public EnhancedRouteZuulFilter(EnhancedPluginRunner pluginRunner, Environment environment) {
this.pluginRunner = pluginRunner;
this.environment = environment;
}
@Override
public String filterType() {
return PRE_TYPE;
return ROUTE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER + 1;
return RIBBON_ROUTING_FILTER_ORDER + 1;
}
@Override
@ -100,9 +102,21 @@ public class EnhancedPreZuulFilter extends ZuulFilter {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
Object ribbonResponseObj = context.get("ribbonResponse");
RibbonApacheHttpResponse ribbonResponse;
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
if (ribbonResponseObj != null && ribbonResponseObj instanceof RibbonApacheHttpResponse) {
ribbonResponse = (RibbonApacheHttpResponse) ribbonResponseObj;
serviceInstance.setServiceId(ZuulFilterUtils.getServiceId(context));
serviceInstance.setHost(ribbonResponse.getRequestedURI().getHost());
serviceInstance.setPort(ribbonResponse.getRequestedURI().getPort());
enhancedPluginContext.setTargetServiceInstance(serviceInstance);
}
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
Object startTimeMilliObject = context.get(POLARIS_PRE_ROUTE_TIME);
if (startTimeMilliObject == null || !(startTimeMilliObject instanceof Long)) {

@ -26,6 +26,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.polaris.client.api.SDKContext;
import feign.Client;
import feign.Request;
import feign.RequestTemplate;
@ -34,6 +35,7 @@ import feign.Target;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ -55,6 +57,9 @@ import static org.mockito.Mockito.mock;
properties = {"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp", "spring.cloud.gateway.enabled=false"})
public class EnhancedFeignClientTest {
@Autowired
private SDKContext sdkContext;
@Test
public void testConstructor() {
try {
@ -75,7 +80,7 @@ public class EnhancedFeignClientTest {
List<EnhancedPlugin> enhancedPlugins = getMockEnhancedFeignPlugins();
try {
new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins));
new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins, null, sdkContext));
}
catch (Throwable e) {
fail("Exception encountered.", e);
@ -104,7 +109,7 @@ public class EnhancedFeignClientTest {
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.feignTarget(target);
EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins()));
EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, sdkContext));
// 200
Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test",
@ -134,7 +139,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.PRE;
return EnhancedPluginType.Client.PRE;
}
@Override
@ -156,7 +161,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
@ -178,7 +183,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
@ -200,7 +205,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.FINALLY;
return EnhancedPluginType.Client.FINALLY;
}
@Override

@ -25,6 +25,9 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
@ -38,6 +41,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -65,6 +69,8 @@ public class EnhancedPluginContextTest {
private SDKContext sdkContext;
@Mock
private ConsumerAPI consumerAPI;
@Mock
private Registration registration;
@BeforeAll
static void beforeAll() {
@ -111,24 +117,38 @@ public class EnhancedPluginContextTest {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
enhancedPluginContext.setRequest(requestContext);
enhancedPluginContext.setResponse(responseContext);
enhancedPluginContext.setServiceInstance(new DefaultServiceInstance());
enhancedPluginContext.setTargetServiceInstance(new DefaultServiceInstance());
enhancedPluginContext.setThrowable(mock(Exception.class));
enhancedPluginContext.setDelay(0);
assertThat(enhancedPluginContext.getRequest()).isNotNull();
assertThat(enhancedPluginContext.getResponse()).isNotNull();
assertThat(enhancedPluginContext.getServiceInstance()).isNotNull();
assertThat(enhancedPluginContext.getTargetServiceInstance()).isNotNull();
assertThat(enhancedPluginContext.getThrowable()).isNotNull();
assertThat(enhancedPluginContext.getDelay()).isNotNull();
EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, sdkContext, consumerAPI);
EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, sdkContext, consumerAPI);
EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1));
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext);
EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, consumerAPI);
EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, consumerAPI);
EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1), registration, sdkContext);
enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
assertThat(enhancedPluginRunner.getLocalServiceInstance()).isEqualTo(registration);
EnhancedPlugin enhancedPlugin2 = mock(EnhancedPlugin.class);
doThrow(new RuntimeException()).when(enhancedPlugin2).run(any());
doReturn(EnhancedPluginType.POST).when(enhancedPlugin2).getType();
enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2));
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext);
doReturn(EnhancedPluginType.Client.POST).when(enhancedPlugin2).getType();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2), null, sdkContext);
enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
}
}

@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -63,8 +60,6 @@ public class ExceptionPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
private RpcEnhancementReporterProperties reporterProperties;
@Mock
private SDKContext sdkContext;
@InjectMocks
private ExceptionPolarisReporter exceptionPolarisReporter;
@Mock
@ -75,6 +70,12 @@ public class ExceptionPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -95,7 +96,7 @@ public class ExceptionPolarisReporterTest {
@Test
public void testType() {
assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION);
assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
@ -107,32 +108,23 @@ public class ExceptionPolarisReporterTest {
doReturn(true).when(reporterProperties).isEnabled();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
pluginContext.setThrowable(new RuntimeException());
exceptionPolarisReporter.run(pluginContext);

@ -15,20 +15,19 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement;
package com.tencent.cloud.rpc.enhancement.plugin;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.rpc.ServiceCallResult;
@ -43,6 +42,7 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@ -54,12 +54,12 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* Test For {@link AbstractPolarisReporterAdapter}.
* Test For {@link PolarisEnhancedPluginUtils}.
*
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022/7/11
*/
@ExtendWith(MockitoExtension.class)
public class AbstractPolarisReporterAdapterTest {
public class PolarisEnhancedPluginUtilsTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private final RpcEnhancementReporterProperties reporterProperties = new RpcEnhancementReporterProperties();
@ -71,6 +71,12 @@ public class AbstractPolarisReporterAdapterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -86,25 +92,18 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testServiceCallResult() throws URISyntaxException {
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext);
ServiceCallResult serviceCallResult;
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add(RouterConstant.ROUTER_LABEL_HEADER, "{\"k1\":\"v1\"}");
serviceCallResult = adapter.createServiceCallResult(
assertThat(PolarisEnhancedPluginUtils.getLabelMap(requestHeaders)).isEqualTo(new HashMap<String, String>() {{
put("k1", "v1");
}});
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -117,7 +116,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -130,7 +130,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetFail);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -143,7 +144,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
"0.0.0.0",
8080,
@ -162,11 +164,9 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testResourceStat() throws URISyntaxException {
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext);
ResourceStat resourceStat;
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -176,7 +176,7 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -186,7 +186,7 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -200,13 +200,32 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testApplyWithDefaultConfig() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
public void testApplyWithHttpStatus() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
properties.setStatuses(Arrays.asList(HttpStatus.BAD_GATEWAY, HttpStatus.INTERNAL_SERVER_ERROR));
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(null)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -216,12 +235,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.setIgnoreInternalServerError(false);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -231,12 +254,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.setIgnoreInternalServerError(true);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -246,12 +273,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.getSeries().clear();
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -262,65 +293,46 @@ public class AbstractPolarisReporterAdapterTest {
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
}
@Test
public void testGetRetStatusFromRequest() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
properties.getStatuses().clear();
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
HttpHeaders headers = new HttpHeaders();
RetStatus ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
RetStatus ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetFail);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc());
ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetFlowControl);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetReject.getDesc());
ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetReject);
}
@Test
public void testGetActiveRuleNameFromRequest() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
properties.getStatuses().clear();
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
HttpHeaders headers = new HttpHeaders();
String ruleName = adapter.getActiveRuleNameFromRequest(headers);
String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("");
headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule");
ruleName = adapter.getActiveRuleNameFromRequest(headers);
ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("mock_rule");
}
/**
* Simple Polaris CircuitBreak Adapter Implements .
*/
public static class SimplePolarisReporterAdapter extends AbstractPolarisReporterAdapter {
protected SimplePolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) {
super(reportProperties, context);
}
}
}

@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -60,8 +57,6 @@ import static org.mockito.Mockito.verify;
public class SuccessPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
private SDKContext sdkContext;
@Mock
private RpcEnhancementReporterProperties reporterProperties;
@InjectMocks
private SuccessPolarisReporter successPolarisReporter;
@ -73,6 +68,12 @@ public class SuccessPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -93,7 +94,7 @@ public class SuccessPolarisReporterTest {
@Test
public void testType() {
assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.POST);
assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
@ -105,31 +106,23 @@ public class SuccessPolarisReporterTest {
verify(context, times(0)).getRequest();
doReturn(true).when(reporterProperties).isEnabled();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
successPolarisReporter.run(pluginContext);
successPolarisReporter.getOrder();

@ -40,6 +40,7 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -65,6 +66,8 @@ public class EnhancedRestTemplateInterceptorTest {
@Mock
private SDKContext sdkContext;
@Mock
Registration registration;
@Mock
private ClientHttpRequestExecution mockClientHttpRequestExecution;
@Mock
private ClientHttpResponse mockClientHttpResponse;
@ -109,7 +112,7 @@ public class EnhancedRestTemplateInterceptorTest {
doReturn(mockHttpHeaders).when(mockHttpRequest).getHeaders();
doReturn(mockClientHttpResponse).when(mockClientHttpRequestExecution).execute(mockHttpRequest, inputBody);
EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
actualResult = reporter.intercept(mockHttpRequest, inputBody, mockClientHttpRequestExecution);
assertThat(actualResult).isEqualTo(mockClientHttpResponse);

@ -17,13 +17,11 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -36,7 +34,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
@ -45,13 +45,16 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
public class BlockingLoadBalancerClientAspectTest {
public class PolarisLoadBalancerRequestTransformerTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private PolarisLoadBalancerRequestTransformer transformer = new PolarisLoadBalancerRequestTransformer();
@Mock
private ProceedingJoinPoint proceedingJoinPoint;
private HttpRequest clientRequest;
private BlockingLoadBalancerClientAspect aspect = new BlockingLoadBalancerClientAspect();
@Mock
private ServiceInstance serviceInstance;
@BeforeAll
static void beforeAll() {
@ -79,14 +82,8 @@ public class BlockingLoadBalancerClientAspectTest {
@Test
public void test() throws Throwable {
ServiceInstance serviceInstance = mock(ServiceInstance.class);
doReturn("0.0.0.0").when(serviceInstance).getHost();
doReturn(80).when(serviceInstance).getPort();
doReturn(new Object[]{ serviceInstance }).when(proceedingJoinPoint).getArgs();
aspect.invoke(proceedingJoinPoint);
aspect.pointcut();
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST)).isEqualTo("0.0.0.0");
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT)).isEqualTo("80");
transformer.transformRequest(clientRequest, serviceInstance);
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance);
}
}

@ -39,6 +39,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.context.ApplicationContext;
@ -62,6 +63,8 @@ public class EnhancedGatewayGlobalFilterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
Registration registration;
@Mock
ServerWebExchange exchange;
@Mock
GatewayFilterChain chain;
@ -115,7 +118,7 @@ public class EnhancedGatewayGlobalFilterTest {
doReturn(request).when(exchange).getRequest();
doReturn(response).when(exchange).getResponse();
EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
reporter.getOrder();
reporter.filter(exchange, chain).block();

@ -39,9 +39,11 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFunction;
@ -56,7 +58,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
public class EnhancedWebClientReporterTest {
public class EnhancedWebClientExchangeFilterFunctionTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
@ -64,6 +66,8 @@ public class EnhancedWebClientReporterTest {
@Mock
private SDKContext sdkContext;
@Mock
private Registration registration;
@Mock
private ClientRequest clientRequest;
@Mock
private ExchangeFunction exchangeFunction;
@ -101,9 +105,10 @@ public class EnhancedWebClientReporterTest {
doReturn(HttpMethod.GET).when(clientRequest).method();
ClientResponse.Headers headers = mock(ClientResponse.Headers.class);
doReturn(headers).when(clientResponse).headers();
doReturn(HttpStatus.valueOf(200)).when(clientResponse).statusCode();
doReturn(Mono.just(clientResponse)).when(exchangeFunction).exchange(any());
EnhancedWebClientReporter reporter = new EnhancedWebClientReporter(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedWebClientExchangeFilterFunction reporter = new EnhancedWebClientExchangeFilterFunction(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
ClientResponse clientResponse1 = reporter.filter(clientRequest, exchangeFunction).block();
assertThat(clientResponse1).isEqualTo(clientResponse);

@ -17,7 +17,6 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
@ -37,6 +36,7 @@ import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.client.ClientRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
@ -83,8 +83,7 @@ public class PolarisLoadBalancerClientRequestTransformerTest {
@Test
public void test() throws Throwable {
doReturn("test").when(serviceInstance).getServiceId();
transformer.transformRequest(clientRequest, serviceInstance);
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID)).isEqualTo("test");
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance);
}
}

Loading…
Cancel
Save