feat: finish discovery ability in 2020.x

pull/12/head
chuntaojun 4 years ago
parent 085ae91f77
commit fa5d0eefb8

@ -14,6 +14,11 @@
<name>Polaris Discovery Callee Service</name> <name>Polaris Discovery Callee Service</name>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency> <dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId> <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>

@ -18,6 +18,11 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency> <dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId> <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId> <groupId>com.tencent.cloud</groupId>

@ -18,6 +18,8 @@
package com.tencent.cloud.polaris.discovery.service.caller; package com.tencent.cloud.polaris.discovery.service.caller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -37,6 +39,12 @@ public class DiscoveryCallerController {
@Autowired @Autowired
private DiscoveryCalleeService discoveryCalleeService; private DiscoveryCalleeService discoveryCalleeService;
@Configuration
@LoadBalancerClient(value = "service-provider")
class DiscoveryCallerConfiguration {
}
/** /**
* *
* *

@ -1,10 +1,11 @@
server: server:
session-timeout: 1800
port: 48080 port: 48080
spring: spring:
application: application:
name: DiscoveryCallerService name: DiscoveryCallerService
cloud: cloud:
loadbalancer:
configurations: default
polaris: polaris:
address: grpc://127.0.0.1:8091 address: grpc://127.0.0.1:8091
consul: consul:

@ -20,6 +20,7 @@
</modules> </modules>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>

@ -23,11 +23,10 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/** /**
* Wrap Spring Bean and decorating proxy for Feign Client. * Wrap Spring Bean and decorating proxy for Feign Client.
@ -50,16 +49,14 @@ public class PolarisFeignBeanPostProcessor implements BeanPostProcessor, BeanFac
} }
private Object wrapper(Object bean) { private Object wrapper(Object bean) {
if (isNeedWrap(bean)) { if (isNeedWrap(bean)) {
if (bean instanceof LoadBalancerFeignClient) {
LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
return new PolarisLoadBalancerFeignClient(createPolarisFeignClient(client.getDelegate()), factory(),
clientFactory());
}
if (bean instanceof FeignBlockingLoadBalancerClient) { if (bean instanceof FeignBlockingLoadBalancerClient) {
FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean; FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean;
return new PolarisFeignBlockingLoadBalancerClient(createPolarisFeignClient(client.getDelegate()), return new PolarisFeignBlockingLoadBalancerClient(createPolarisFeignClient(client.getDelegate()),
factory.getBean(BlockingLoadBalancerClient.class)); factory.getBean(BlockingLoadBalancerClient.class),
factory.getBean(LoadBalancerProperties.class),
factory.getBean(LoadBalancerClientFactory.class));
} }
return createPolarisFeignClient((Client) bean); return createPolarisFeignClient((Client) bean);
} }
@ -68,8 +65,7 @@ public class PolarisFeignBeanPostProcessor implements BeanPostProcessor, BeanFac
private boolean isNeedWrap(Object bean) { private boolean isNeedWrap(Object bean) {
return bean instanceof Client && !(bean instanceof PolarisFeignClient) return bean instanceof Client && !(bean instanceof PolarisFeignClient)
&& !(bean instanceof PolarisFeignBlockingLoadBalancerClient) && !(bean instanceof PolarisFeignBlockingLoadBalancerClient);
&& !(bean instanceof PolarisLoadBalancerFeignClient);
} }
private PolarisFeignClient createPolarisFeignClient(Client delegate) { private PolarisFeignClient createPolarisFeignClient(Client delegate) {
@ -80,12 +76,4 @@ public class PolarisFeignBeanPostProcessor implements BeanPostProcessor, BeanFac
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.factory = beanFactory; this.factory = beanFactory;
} }
CachingSpringLoadBalancerFactory factory() {
return this.factory.getBean(CachingSpringLoadBalancerFactory.class);
}
SpringClientFactory clientFactory() {
return this.factory.getBean(SpringClientFactory.class);
}
} }

@ -18,7 +18,10 @@
package com.tencent.cloud.polaris.circuitbreaker.feign; package com.tencent.cloud.polaris.circuitbreaker.feign;
import feign.Client; import feign.Client;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
/** /**
@ -28,9 +31,11 @@ import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalance
*/ */
public class PolarisFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient { public class PolarisFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient {
public PolarisFeignBlockingLoadBalancerClient(Client delegate, public PolarisFeignBlockingLoadBalancerClient(Client delegate,
BlockingLoadBalancerClient loadBalancerClient) { LoadBalancerClient loadBalancerClient,
super(delegate, loadBalancerClient); LoadBalancerProperties properties,
LoadBalancerClientFactory loadBalancerClientFactory) {
super(delegate, loadBalancerClient, properties, loadBalancerClientFactory);
} }
} }

@ -1,37 +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.polaris.circuitbreaker.feign;
import feign.Client;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/**
* Wrap for {@link LoadBalancerFeignClient}
*
* @author Haotian Zhang
*/
public class PolarisLoadBalancerFeignClient extends LoadBalancerFeignClient {
public PolarisLoadBalancerFeignClient(Client delegate,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
}

@ -51,9 +51,6 @@ public class PolarisFeignClientTest {
if (client instanceof PolarisFeignClient) { if (client instanceof PolarisFeignClient) {
return; return;
} }
if (client instanceof PolarisLoadBalancerFeignClient) {
return;
}
if (client instanceof PolarisFeignBlockingLoadBalancerClient) { if (client instanceof PolarisFeignBlockingLoadBalancerClient) {
return; return;
} }

@ -37,6 +37,11 @@
<artifactId>polaris-discovery-factory</artifactId> <artifactId>polaris-discovery-factory</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-router-factory</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.tencent.polaris</groupId> <groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId> <artifactId>polaris-test-common</artifactId>
@ -91,11 +96,6 @@
<artifactId>powermock-api-mockito2</artifactId> <artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -69,8 +69,8 @@ public class PolarisProperties {
/** /**
* 使spring cloud * 使spring cloud
*/ */
@Value("${server.port:}") @Value("${server.port:#{-1}}")
private int port; private int port = -1;
/** /**
* *
@ -78,14 +78,12 @@ public class PolarisProperties {
@Value("${spring.cloud.polaris.discovery.loadbalancer.enabled:#{true}}") @Value("${spring.cloud.polaris.discovery.loadbalancer.enabled:#{true}}")
private Boolean loadbalancerEnabled; private Boolean loadbalancerEnabled;
/** /**
* loadbalnce strategy * loadbalnce strategy
*/ */
@Value("${spring.cloud.polaris.discovery.loadbalancer.policy:#{'weightedRandom'}}") @Value("${spring.cloud.polaris.discovery.loadbalancer.policy:#{'weightedRandom'}}")
private String policy; private String policy;
/** /**
* loadbalnce strategy * loadbalnce strategy
*/ */

@ -17,8 +17,26 @@
package com.tencent.cloud.polaris.loadbalancer; package com.tencent.cloud.polaris.loadbalancer;
import com.tencent.cloud.constant.LoadbalancerConstant;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
/** /**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
@ -27,4 +45,49 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnDiscoveryEnabled @ConditionalOnDiscoveryEnabled
public class PolarisLoadBalancerClientConfiguration { public class PolarisLoadBalancerClientConfiguration {
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory,
PolarisProperties polarisProperties,
RouterAPI routerAPI) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new PolarisLoadbalancer(
name, loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
polarisProperties, routerAPI);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnReactiveDiscoveryEnabled
@Order(LoadbalancerConstant.DISCOVERY_SERVICE_INSTANCE_SUPPLIER_ORDER)
public static class ReactiveSupportConfiguration {
@Bean
@ConditionalOnBean(ReactiveDiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", matchIfMissing = true)
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder().withDiscoveryClient()
.build(context);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBlockingDiscoveryEnabled
@Order(LoadbalancerConstant.DISCOVERY_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)
public static class BlockingSupportConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", matchIfMissing = true)
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()
.build(context);
}
}
} }

@ -18,8 +18,21 @@
package com.tencent.cloud.polaris.loadbalancer; package com.tencent.cloud.polaris.loadbalancer;
import com.tencent.cloud.metadata.context.MetadataContextHolder;
import com.tencent.cloud.polaris.PolarisProperties; import com.tencent.cloud.polaris.PolarisProperties;
import java.util.List; import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.tencent.cloud.polaris.pojo.PolarisServiceInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.Criteria;
import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceRequest;
import com.tencent.polaris.router.api.rpc.ProcessLoadBalanceResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
@ -30,13 +43,14 @@ import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response; import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
/** /**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/ */
public class PolarisLoadbalancer implements ReactorServiceInstanceLoadBalancer { public class PolarisLoadbalancer extends RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final Logger log = LoggerFactory.getLogger(PolarisLoadbalancer.class); private static final Logger log = LoggerFactory.getLogger(PolarisLoadbalancer.class);
@ -46,16 +60,23 @@ public class PolarisLoadbalancer implements ReactorServiceInstanceLoadBalancer {
private final PolarisProperties discoveryProperties; private final PolarisProperties discoveryProperties;
private final RouterAPI routerAPI;
public PolarisLoadbalancer(String serviceId, public PolarisLoadbalancer(String serviceId,
ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider, ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider,
PolarisProperties discoveryProperties) { PolarisProperties discoveryProperties, RouterAPI routerAPI) {
super(supplierObjectProvider, serviceId);
this.serviceId = serviceId; this.serviceId = serviceId;
this.supplierObjectProvider = supplierObjectProvider; this.supplierObjectProvider = supplierObjectProvider;
this.discoveryProperties = discoveryProperties; this.discoveryProperties = discoveryProperties;
this.routerAPI = routerAPI;
} }
@Override @Override
public Mono<Response<ServiceInstance>> choose(Request request) { public Mono<Response<ServiceInstance>> choose(Request request) {
if (!discoveryProperties.getLoadbalancerEnabled()) {
return super.choose(request);
}
ServiceInstanceListSupplier supplier = supplierObjectProvider.getIfAvailable(NoopServiceInstanceListSupplier::new); ServiceInstanceListSupplier supplier = supplierObjectProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get().next().map(this::getInstanceResponse); return supplier.get().next().map(this::getInstanceResponse);
} }
@ -66,15 +87,28 @@ public class PolarisLoadbalancer implements ReactorServiceInstanceLoadBalancer {
return new EmptyResponse(); return new EmptyResponse();
} }
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
request.setDstInstances(convertToPolarisServiceInstances(serviceInstances));
request.setLbPolicy(discoveryProperties.getPolicy());
request.setCriteria(new Criteria());
try { try {
ServiceInstance instance = NacosBalancer.getHostByRandomWeight3(serviceInstances); ProcessLoadBalanceResponse response = routerAPI.processLoadBalance(request);
return new DefaultResponse(instance); return new DefaultResponse(new PolarisServiceInstance(response.getTargetInstance()));
} }
catch (Exception e) { catch (Exception e) {
log.warn("NacosLoadBalancer error", e); log.warn("PolarisLoadbalancer error", e);
return new EmptyResponse(); return new EmptyResponse();
} }
}
private static ServiceInstances convertToPolarisServiceInstances(List<ServiceInstance> serviceInstances) {
ServiceKey serviceKey = new ServiceKey(MetadataContextHolder.LOCAL_NAMESPACE, serviceInstances.get(0).getServiceId());
List<Instance> polarisInstances = serviceInstances
.stream()
.map(serviceInstance -> ((PolarisServiceInstance) serviceInstance).getPolarisInstance())
.collect(Collectors.toList());
return new DefaultServiceInstances(serviceKey, polarisInstances);
} }
} }

@ -23,6 +23,7 @@ import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegis
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -43,9 +44,10 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
@Override @Override
protected PolarisRegistration getRegistration() { protected PolarisRegistration getRegistration() {
if (this.registration.getPort() <= 0) { if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
this.registration.setPort(this.getPort().get()); this.registration.setPort(this.getPort().get());
} }
Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
return this.registration; return this.registration;
} }

@ -175,9 +175,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
* @param heartbeatRequest * @param heartbeatRequest
*/ */
public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) { public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) {
heartbeatExecutor.scheduleWithFixedDelay(new Runnable() { heartbeatExecutor.scheduleWithFixedDelay(() -> {
@Override
public void run() {
try { try {
polarisDiscoveryHandler.getProviderAPI().heartbeat(heartbeatRequest); polarisDiscoveryHandler.getProviderAPI().heartbeat(heartbeatRequest);
} catch (PolarisException e) { } catch (PolarisException e) {
@ -185,7 +183,6 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
} catch (Exception e) { } catch (Exception e) {
log.error("polaris heartbeat runtime error", e); log.error("polaris heartbeat runtime error", e);
} }
}
}, 0, ttl, TimeUnit.SECONDS); }, 0, ttl, TimeUnit.SECONDS);
} }

@ -1,5 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration,\ com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration,\
com.tencent.cloud.polaris.ribbon.PolarisDiscoveryRibbonAutoConfiguration,\
com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration

@ -22,8 +22,6 @@ import static com.tencent.polaris.test.common.Consts.PORT;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import org.junit.Test; import org.junit.Test;
@ -40,7 +38,6 @@ public class PolarisRibbonServerListAutoConfigurationTest {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
PolarisRibbonClientTest.class,
PolarisDiscoveryClientConfiguration.class)) PolarisDiscoveryClientConfiguration.class))
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
.withPropertyValues("server.port=" + PORT) .withPropertyValues("server.port=" + PORT)
@ -48,36 +45,4 @@ public class PolarisRibbonServerListAutoConfigurationTest {
.withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST) .withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx"); .withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
@Test
public void testProperties() {
this.contextRunner.run(context -> {
PolarisDiscoveryHandler discoveryHandler = context.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(discoveryHandler);
IClientConfig iClientConfig = context.getBean(IClientConfig.class);
serverList.initWithNiwsConfig(iClientConfig);
assertThat(serverList.getServiceId()).isEqualTo(SERVICE_PROVIDER);
});
}
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
static class PolarisRibbonClientTest {
@Bean
IClientConfig iClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName(SERVICE_PROVIDER);
return config;
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
} }

@ -24,13 +24,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration; import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import java.util.List;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.test.mock.discovery.NamingServer; import com.tencent.polaris.test.mock.discovery.NamingServer;
@ -75,56 +72,6 @@ public class PolarisServerListTest {
} }
} }
/**
* Test {@link PolarisServerList#getInitialListOfServers()} with empty server list.
*/
@Test
@SuppressWarnings("unchecked")
public void test1(){
this.contextRunner.run(context -> {
// mock
IClientConfig iClientConfig = mock(IClientConfig.class);
when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER);
PolarisDiscoveryHandler polarisDiscoveryHandler = context.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
List<Server> servers = serverList.getInitialListOfServers();
assertThat(servers).isEmpty();
});
}
/**
* Test {@link PolarisServerList#getUpdatedListOfServers()} with server list of size 3.
*/
@Test
@SuppressWarnings("unchecked")
public void test2() throws Exception {
this.contextRunner.run(context -> {
// mock
IClientConfig iClientConfig = mock(IClientConfig.class);
when(iClientConfig.getClientName()).thenReturn(SERVICE_PROVIDER);
PolarisDiscoveryHandler polarisDiscoveryHandler = context.getBean(PolarisDiscoveryHandler.class);
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
// add service with 3 instances
NamingService.InstanceParameter instanceParameter = new NamingService.InstanceParameter();
instanceParameter.setHealthy(true);
instanceParameter.setIsolated(false);
instanceParameter.setWeight(100);
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER);
namingServer.getNamingService().batchAddInstances(serviceKey, PORT, 3, instanceParameter);
List<Server> servers = serverList.getUpdatedListOfServers();
assertThat(servers).hasSize(3);
assertThat(servers.get(0).getPort()).isEqualTo(PORT);
assertThat(servers.get(1).getPort()).isEqualTo(PORT + 1);
assertThat(servers.get(2).getPort()).isEqualTo(PORT + 2);
});
}
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@EnableDiscoveryClient @EnableDiscoveryClient

@ -34,7 +34,6 @@
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId> <artifactId>spring-cloud-loadbalancer</artifactId>
<optional>true</optional>
</dependency> </dependency>
<!-- Polaris dependencies start --> <!-- Polaris dependencies start -->

@ -0,0 +1,112 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.router;
import com.tencent.cloud.constant.LoadbalancerConstant;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.RouterAPIFactory;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
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.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
/**
* Auto-configuration Ribbon for Polaris.
*
* @author Haotian Zhang
*/
@Configuration()
@EnableConfigurationProperties
@ConditionalOnProperty(value = "spring.cloud.polaris.loadbalancer.enabled", matchIfMissing = true)
public class PolarisRouterAutoConfiguration {
@Bean(name = "polarisRoute")
@ConditionalOnMissingBean
public RouterAPI polarisRouter(SDKContext polarisContext) throws PolarisException {
return RouterAPIFactory.createRouterAPIByContext(polarisContext);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnReactiveDiscoveryEnabled
@Order(LoadbalancerConstant.ROUTER_SERVICE_INSTANCE_SUPPLIER_ORDER - 1000)
public static class ReactiveSupportConfiguration {
// @Bean
// @ConditionalOnBean(ReactiveDiscoveryClient.class)
// @ConditionalOnMissingBean
// @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", matchIfMissing = true)
// public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
// ConfigurableApplicationContext context) {
// return new PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier.builder().withDiscoveryClient()
// .build(context), routerAPI);
// }
@Bean
@ConditionalOnBean(ReactiveDiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference", matchIfMissing = true)
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
ConfigurableApplicationContext context) {
return new PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier.builder().withDiscoveryClient()
.withZonePreference()
.build(context), routerAPI);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBlockingDiscoveryEnabled
@Order(LoadbalancerConstant.ROUTER_SERVICE_INSTANCE_SUPPLIER_ORDER + 1 - 1000)
public static class BlockingSupportConfiguration {
// @Bean
// @ConditionalOnBean(DiscoveryClient.class)
// @ConditionalOnMissingBean
// @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", matchIfMissing = true)
// public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
// RouterAPI routerAPI,
// ConfigurableApplicationContext context) {
// return new PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()
// .build(context), routerAPI);
// }
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference", matchIfMissing = true)
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
ConfigurableApplicationContext context) {
return new PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()
.withZonePreference().build(context), routerAPI);
}
}
}

@ -34,19 +34,34 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Flux;
/** /**
* @author Haotian Zhang * @author Haotian Zhang
*/ */
public class PolarisRoutingLoadBalancer { public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier {
private final RouterAPI routerAPI; private final RouterAPI routerAPI;
public PolarisRoutingLoadBalancer(RouterAPI routerAPI) { public PolarisRouterServiceInstanceListSupplier(ServiceInstanceListSupplier delegate, RouterAPI routerAPI) {
super(delegate);
this.routerAPI = routerAPI; this.routerAPI = routerAPI;
} }
@Override
public Flux<List<ServiceInstance>> get() {
return getDelegate().get().map(this::chooseInstances);
}
@Override
public Flux<List<ServiceInstance>> get(Request request) {
return super.get(request);
}
public List<ServiceInstance> chooseInstances(List<ServiceInstance> allServers) { public List<ServiceInstance> chooseInstances(List<ServiceInstance> allServers) {
if (CollectionUtils.isEmpty(allServers)) { if (CollectionUtils.isEmpty(allServers)) {
return allServers; return allServers;
@ -93,5 +108,4 @@ public class PolarisRoutingLoadBalancer {
} }
return filteredInstances; return filteredInstances;
} }
} }

@ -1,51 +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.polaris.router.config;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.RouterAPIFactory;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto-configuration Ribbon for Polaris.
*
* @author Haotian Zhang
*/
@Configuration()
@EnableConfigurationProperties
@ConditionalOnProperty(value = "spring.cloud.polaris.loadbalancer.enabled", matchIfMissing = true)
public class PolarisRouterAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisRouterProperties polarisRibbonProperties() {
return new PolarisRouterProperties();
}
@Bean(name = "polarisRoute")
@ConditionalOnMissingBean
public RouterAPI polarisRouter(SDKContext polarisContext) throws PolarisException {
return RouterAPIFactory.createRouterAPIByContext(polarisContext);
}
}

@ -1,64 +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.polaris.router.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Haotian Zhang
*/
@ConfigurationProperties("spring.cloud.polaris.ribbon")
public class PolarisRouterProperties {
/**
*
*/
@Value("${spring.cloud.polaris.loadbalancer.enabled:#{true}}")
private Boolean loadbalancerEnabled;
/**
* loadbalnce strategy
*/
@Value("${spring.cloud.polaris.loadbalancer.strategy:#{'weightedRandom'}}")
private String policy;
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
public Boolean getLoadbalancerEnabled() {
return loadbalancerEnabled;
}
public void setLoadbalancerEnabled(Boolean loadbalancerEnabled) {
this.loadbalancerEnabled = loadbalancerEnabled;
}
@Override
public String toString() {
return "PolarisRibbonProperties{" +
"loadbalancerEnabled=" + loadbalancerEnabled +
", policy='" + policy + '\'' +
'}';
}
}

@ -1,53 +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.polaris.router.rule;
import java.util.Arrays;
/**
* @author Haotian Zhang
*/
public enum PolarisLoadBalanceRule {
/**
*
*/
WEIGHTED_RANDOM_RULE("weighted_random");
/**
*
*/
String policy;
PolarisLoadBalanceRule(String strategy) {
this.policy = strategy;
}
public static PolarisLoadBalanceRule fromStrategy(String strategy) {
return Arrays.stream(values()).filter(t -> t.getPolicy().equals(strategy)).findAny()
.orElse(WEIGHTED_RANDOM_RULE);
}
/**
* {@link #policy}getter
*/
public String getPolicy() {
return policy;
}
}

@ -1,2 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.router.config.PolarisRouterAutoConfiguration com.tencent.cloud.polaris.router.PolarisRouterAutoConfiguration

@ -17,6 +17,7 @@
package com.tencent.cloud.polaris.router.config; package com.tencent.cloud.polaris.router.config;
import com.tencent.cloud.polaris.router.PolarisRouterAutoConfiguration;
import com.tencent.polaris.router.api.core.RouterAPI; import com.tencent.polaris.router.api.core.RouterAPI;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -41,14 +42,6 @@ public class PolarisRibbonAutoConfigurationTest {
.withPropertyValues("server.port=" + PORT) .withPropertyValues("server.port=" + PORT)
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081"); .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081");
@Test
public void testDefaultInitialization() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterAPI.class);
assertThat(context).hasSingleBean(PolarisRouterProperties.class);
});
}
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
static class PolarisRibbonTest { static class PolarisRibbonTest {

@ -15,19 +15,20 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.router.config; package com.tencent.cloud.constant;
import com.tencent.cloud.polaris.router.PolarisRoutingLoadBalancer; /**
import com.tencent.cloud.polaris.router.rule.PolarisLoadBalanceRule; * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
import com.tencent.polaris.router.api.core.RouterAPI; */
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; public final class LoadbalancerConstant {
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; private LoadbalancerConstant() {}
public static final int DISCOVERY_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465 - 1000000;
/** /**
* @author Haotian Zhang * We need to ensure that the routing action is performed before the load balancing action can be performed
*/ */
@Configuration public static final int ROUTER_SERVICE_INSTANCE_SUPPLIER_ORDER = DISCOVERY_SERVICE_INSTANCE_SUPPLIER_ORDER - 1000000;
public class PolarisRouterClientConfiguration {
} }

@ -48,6 +48,10 @@ public class PolarisServiceInstance implements ServiceInstance {
} }
} }
public Instance getPolarisInstance() {
return instance;
}
@Override @Override
public String getInstanceId() { public String getInstanceId() {
return ServiceInstance.super.getInstanceId(); return ServiceInstance.super.getInstanceId();

@ -22,13 +22,16 @@ import feign.Contract;
import feign.Feign; import feign.Feign;
import feign.InvocationHandlerFactory; import feign.InvocationHandlerFactory;
import feign.Target; import feign.Target;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.cloud.openfeign.FeignContext; import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
@ -85,7 +88,10 @@ public class PluggableFeign {
super.invocationHandlerFactory(new InvocationHandlerFactory() { super.invocationHandlerFactory(new InvocationHandlerFactory() {
@Override @Override
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) { public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
Object feignClientFactoryBean = applicationContext.getBean("&" + target.type().getName()); GenericApplicationContext gctx = (GenericApplicationContext) Builder.this.applicationContext;
BeanDefinition def = gctx.getBeanDefinition(target.type().getName());
FeignClientFactoryBean feignClientFactoryBean = (FeignClientFactoryBean) def.getAttribute("feignClientsRegistrarFactoryBean");
Class fallback = (Class) ReflectionUtils.getFieldValue(feignClientFactoryBean, "fallback"); Class fallback = (Class) ReflectionUtils.getFieldValue(feignClientFactoryBean, "fallback");
Class fallbackFactory = (Class) ReflectionUtils.getFieldValue(feignClientFactoryBean, Class fallbackFactory = (Class) ReflectionUtils.getFieldValue(feignClientFactoryBean,
@ -104,8 +110,7 @@ public class PluggableFeign {
if (void.class != fallback) { if (void.class != fallback) {
fallbackInstance = getFallbackInstanceFromContext(beanName, "fallback", fallback, fallbackInstance = getFallbackInstanceFromContext(beanName, "fallback", fallback,
target.type()); target.type());
return new PluggableFeignInvocationHandler(target, dispatch, return new PluggableFeignInvocationHandler(target, dispatch, (FallbackFactory) fallbackInstance, pluggableFeignPlugins);
new FallbackFactory.Default<>(fallbackInstance), pluggableFeignPlugins);
} }
if (void.class != fallbackFactory) { if (void.class != fallbackFactory) {

@ -20,7 +20,7 @@ package com.tencent.cloud.feign;
import feign.FeignException; import feign.FeignException;
import feign.InvocationHandlerFactory; import feign.InvocationHandlerFactory;
import feign.Target; import feign.Target;
import feign.hystrix.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
@ -36,7 +36,7 @@ public class PluggableFeignContext {
private Map<Method, InvocationHandlerFactory.MethodHandler> dispatch; private Map<Method, InvocationHandlerFactory.MethodHandler> dispatch;
private FallbackFactory fallbackFactory; private FallbackFactory<?> fallbackFactory;
private Map<Method, Method> fallbackMethodMap; private Map<Method, Method> fallbackMethodMap;
@ -66,11 +66,11 @@ public class PluggableFeignContext {
this.dispatch = dispatch; this.dispatch = dispatch;
} }
public FallbackFactory getFallbackFactory() { public FallbackFactory<?> getFallbackFactory() {
return fallbackFactory; return fallbackFactory;
} }
public void setFallbackFactory(FallbackFactory fallbackFactory) { public void setFallbackFactory(FallbackFactory<?> fallbackFactory) {
this.fallbackFactory = fallbackFactory; this.fallbackFactory = fallbackFactory;
} }

@ -20,9 +20,9 @@ package com.tencent.cloud.feign;
import feign.FeignException; import feign.FeignException;
import feign.InvocationHandlerFactory; import feign.InvocationHandlerFactory;
import feign.Target; import feign.Target;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
@ -48,7 +48,7 @@ public class PluggableFeignInvocationHandler implements InvocationHandler {
private final Map<Method, InvocationHandlerFactory.MethodHandler> dispatch; private final Map<Method, InvocationHandlerFactory.MethodHandler> dispatch;
private FallbackFactory fallbackFactory; private FallbackFactory<?> fallbackFactory;
private Map<Method, Method> fallbackMethodMap; private Map<Method, Method> fallbackMethodMap;
@ -59,7 +59,7 @@ public class PluggableFeignInvocationHandler implements InvocationHandler {
private List<PluggableFeignPlugin> exceptionPluggableFeignPlugins; private List<PluggableFeignPlugin> exceptionPluggableFeignPlugins;
PluggableFeignInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch, PluggableFeignInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch,
FallbackFactory fallbackFactory, List<PluggableFeignPlugin> pluggableFeignPlugins) { FallbackFactory<?> fallbackFactory, List<PluggableFeignPlugin> pluggableFeignPlugins) {
this.target = checkNotNull(target, "target"); this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch"); this.dispatch = checkNotNull(dispatch, "dispatch");
this.fallbackFactory = fallbackFactory; this.fallbackFactory = fallbackFactory;
@ -110,7 +110,9 @@ public class PluggableFeignInvocationHandler implements InvocationHandler {
prePlugin.run(context); prePlugin.run(context);
} }
result = this.dispatch.get(method).invoke(args); InvocationHandlerFactory.MethodHandler handler = this.dispatch.get(method);
result = handler.invoke(args);
context.setResult(result); context.setResult(result);

@ -31,7 +31,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Map; import java.util.Map;
import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER; import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
/** /**
* Scg filter used for writing metadata in HTTP request header. * Scg filter used for writing metadata in HTTP request header.

Loading…
Cancel
Save