parent
9f5bc3b0b7
commit
2781270c16
@ -1,84 +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.metadata.core.filter.gateway;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.netflix.zuul.ZuulFilter;
|
|
||||||
import com.netflix.zuul.context.RequestContext;
|
|
||||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContext;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContextHolder;
|
|
||||||
import com.tencent.cloud.common.util.JacksonUtils;
|
|
||||||
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zuul filter used for writing metadata in HTTP request header.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class Metadata2HeaderZuulFilter extends ZuulFilter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String filterType() {
|
|
||||||
return ROUTE_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int filterOrder() {
|
|
||||||
return RIBBON_ROUTING_FILTER_ORDER - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldFilter() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object run() {
|
|
||||||
// get request context
|
|
||||||
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
||||||
|
|
||||||
// get metadata of current thread
|
|
||||||
MetadataContext metadataContext = MetadataContextHolder.get();
|
|
||||||
|
|
||||||
// add new metadata and cover old
|
|
||||||
Map<String, String> customMetadata = metadataContext
|
|
||||||
.getAllTransitiveCustomMetadata();
|
|
||||||
if (!CollectionUtils.isEmpty(customMetadata)) {
|
|
||||||
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
|
|
||||||
try {
|
|
||||||
requestContext.addZuulRequestHeader(
|
|
||||||
MetadataConstant.HeaderName.CUSTOM_METADATA,
|
|
||||||
URLEncoder.encode(metadataStr, "UTF-8"));
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
requestContext.addZuulRequestHeader(
|
|
||||||
MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,39 +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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +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.ribbon;
|
|
||||||
|
|
||||||
import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Autoconfiguration of ribbon of Polaris.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang, Andrew Shan, Jie Cheng
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@EnableConfigurationProperties
|
|
||||||
@ConditionalOnPolarisDiscoveryEnabled
|
|
||||||
@AutoConfigureAfter(RibbonAutoConfiguration.class)
|
|
||||||
@RibbonClients(defaultConfiguration = PolarisRibbonServerListConfiguration.class)
|
|
||||||
public class PolarisDiscoveryRibbonAutoConfiguration {
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +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.ribbon;
|
|
||||||
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.netflix.loadbalancer.ServerList;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration of server list.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang, Andrew Shan, Jie Cheng
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class PolarisRibbonServerListConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public ServerList<Server> ribbonServerList(
|
|
||||||
PolarisDiscoveryHandler polarisDiscoveryHandler,
|
|
||||||
IClientConfig iClientConfig) {
|
|
||||||
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
|
|
||||||
serverList.initWithNiwsConfig(iClientConfig);
|
|
||||||
return serverList;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,77 +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.ribbon;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.AbstractServerList;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.tencent.cloud.common.pojo.PolarisServer;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
|
|
||||||
import com.tencent.polaris.api.pojo.Instance;
|
|
||||||
import com.tencent.polaris.api.pojo.ServiceInstances;
|
|
||||||
import com.tencent.polaris.api.rpc.InstancesResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server list of Polaris.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang, Andrew Shan, Jie Cheng
|
|
||||||
*/
|
|
||||||
public class PolarisServerList extends AbstractServerList<Server> {
|
|
||||||
|
|
||||||
private String serviceId;
|
|
||||||
|
|
||||||
private PolarisDiscoveryHandler polarisDiscoveryHandler;
|
|
||||||
|
|
||||||
public PolarisServerList(PolarisDiscoveryHandler polarisDiscoveryHandler) {
|
|
||||||
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Server> getInitialListOfServers() {
|
|
||||||
return getServers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Server> getUpdatedListOfServers() {
|
|
||||||
return getServers();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Server> getServers() {
|
|
||||||
InstancesResponse filteredInstances = polarisDiscoveryHandler
|
|
||||||
.getFilteredInstances(serviceId);
|
|
||||||
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
|
|
||||||
List<Server> polarisServers = new ArrayList<>();
|
|
||||||
for (Instance instance : serviceInstances.getInstances()) {
|
|
||||||
polarisServers.add(new PolarisServer(serviceInstances, instance));
|
|
||||||
}
|
|
||||||
return polarisServers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getServiceId() {
|
|
||||||
return serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initWithNiwsConfig(IClientConfig iClientConfig) {
|
|
||||||
this.serviceId = iClientConfig.getClientName();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,3 @@
|
|||||||
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
|
||||||
|
@ -1,92 +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.ribbon;
|
|
||||||
|
|
||||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
|
|
||||||
import static com.tencent.polaris.test.common.Consts.PORT;
|
|
||||||
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for {@link PolarisRibbonServerListConfiguration}
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class PolarisRibbonServerListConfigurationTest {
|
|
||||||
|
|
||||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(PolarisRibbonClientTest.class,
|
|
||||||
PolarisDiscoveryClientConfiguration.class,
|
|
||||||
PolarisContextConfiguration.class))
|
|
||||||
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
|
|
||||||
.withPropertyValues("server.port=" + PORT)
|
|
||||||
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
|
|
||||||
.withPropertyValues(
|
|
||||||
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
|
|
||||||
.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,146 +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.ribbon;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration;
|
|
||||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
|
|
||||||
import com.tencent.polaris.api.pojo.ServiceKey;
|
|
||||||
import com.tencent.polaris.test.mock.discovery.NamingServer;
|
|
||||||
import com.tencent.polaris.test.mock.discovery.NamingService;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
|
|
||||||
import static com.tencent.polaris.test.common.Consts.PORT;
|
|
||||||
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for {@link PolarisServerList}
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class PolarisServerListTest {
|
|
||||||
|
|
||||||
private static NamingServer namingServer;
|
|
||||||
|
|
||||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(PolarisContextConfiguration.class,
|
|
||||||
PolarisServerListTest.PolarisPropertiesConfiguration.class,
|
|
||||||
PolarisDiscoveryClientConfiguration.class,
|
|
||||||
PolarisDiscoveryAutoConfiguration.class,
|
|
||||||
PolarisContextConfiguration.class))
|
|
||||||
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
|
|
||||||
.withPropertyValues("server.port=" + PORT)
|
|
||||||
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
|
|
||||||
.withPropertyValues(
|
|
||||||
"spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST)
|
|
||||||
.withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx");
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
namingServer = NamingServer.startNamingServer(10081);
|
|
||||||
|
|
||||||
// add service
|
|
||||||
namingServer.getNamingService()
|
|
||||||
.addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER));
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClass() throws Exception {
|
|
||||||
if (null != namingServer) {
|
|
||||||
namingServer.terminate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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() {
|
|
||||||
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
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
@EnableDiscoveryClient
|
|
||||||
static class PolarisPropertiesConfiguration {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.metadata.MetadataContext;
|
||||||
|
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
|
||||||
|
import com.tencent.cloud.polaris.router.config.PolarisLoadBalancerProperties;
|
||||||
|
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.LoggerFactory;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.Request;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.Response;
|
||||||
|
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
|
||||||
|
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
|
||||||
|
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
|
||||||
|
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loadbalancer of Polaris.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
public class PolarisRoutingLoadbalancer extends RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PolarisRoutingLoadbalancer.class);
|
||||||
|
|
||||||
|
private final String serviceId;
|
||||||
|
|
||||||
|
private final PolarisLoadBalancerProperties loadBalancerProperties;
|
||||||
|
|
||||||
|
private final RouterAPI routerAPI;
|
||||||
|
|
||||||
|
private ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider;
|
||||||
|
|
||||||
|
public PolarisRoutingLoadbalancer(String serviceId,
|
||||||
|
ObjectProvider<ServiceInstanceListSupplier> supplierObjectProvider,
|
||||||
|
PolarisLoadBalancerProperties loadBalancerProperties, RouterAPI routerAPI) {
|
||||||
|
super(supplierObjectProvider, serviceId);
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
this.supplierObjectProvider = supplierObjectProvider;
|
||||||
|
this.loadBalancerProperties = loadBalancerProperties;
|
||||||
|
this.routerAPI = routerAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceInstances convertToPolarisServiceInstances(List<ServiceInstance> serviceInstances) {
|
||||||
|
ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceInstances.get(0).getServiceId());
|
||||||
|
List<Instance> polarisInstances = serviceInstances.stream()
|
||||||
|
.map(serviceInstance -> ((PolarisServiceInstance) serviceInstance).getPolarisInstance())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return new DefaultServiceInstances(serviceKey, polarisInstances);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Response<ServiceInstance>> choose(Request request) {
|
||||||
|
if (!loadBalancerProperties.getLoadbalancerEnabled()) {
|
||||||
|
return super.choose(request);
|
||||||
|
}
|
||||||
|
ServiceInstanceListSupplier supplier = supplierObjectProvider
|
||||||
|
.getIfAvailable(NoopServiceInstanceListSupplier::new);
|
||||||
|
return supplier.get().next().map(this::getInstanceResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> serviceInstances) {
|
||||||
|
if (serviceInstances.isEmpty()) {
|
||||||
|
log.warn("No servers available for service: " + this.serviceId);
|
||||||
|
return new EmptyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
|
||||||
|
request.setDstInstances(convertToPolarisServiceInstances(serviceInstances));
|
||||||
|
request.setLbPolicy(loadBalancerProperties.getStrategy());
|
||||||
|
request.setCriteria(new Criteria());
|
||||||
|
|
||||||
|
try {
|
||||||
|
ProcessLoadBalanceResponse response = routerAPI.processLoadBalance(request);
|
||||||
|
return new DefaultResponse(new PolarisServiceInstance(response.getTargetInstance()));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
log.warn("PolarisRoutingLoadbalancer error", e);
|
||||||
|
return new EmptyResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* 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.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
|
||||||
|
import com.tencent.cloud.polaris.router.PolarisRoutingLoadbalancer;
|
||||||
|
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.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.core.annotation.Order;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration of loadbalancer client.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnDiscoveryEnabled
|
||||||
|
public class PolarisLoadBalancerClientConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order of reactive discovery service instance supplier.
|
||||||
|
*/
|
||||||
|
private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465;
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ReactorLoadBalancer<ServiceInstance> polarisLoadBalancer(Environment environment,
|
||||||
|
LoadBalancerClientFactory loadBalancerClientFactory, PolarisLoadBalancerProperties loadBalancerProperties,
|
||||||
|
RouterAPI routerAPI) {
|
||||||
|
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
|
||||||
|
return new PolarisRoutingLoadbalancer(name,
|
||||||
|
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
|
||||||
|
loadBalancerProperties, routerAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnReactiveDiscoveryEnabled
|
||||||
|
@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)
|
||||||
|
static class PolarisReactiveSupportConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(ReactiveDiscoveryClient.class)
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "polaris")
|
||||||
|
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
return new PolarisRouterServiceInstanceListSupplier(
|
||||||
|
ServiceInstanceListSupplier.builder().withDiscoveryClient().build(context), routerAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBlockingDiscoveryEnabled
|
||||||
|
@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)
|
||||||
|
static class PolarisBlockingSupportConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(DiscoveryClient.class)
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "polaris")
|
||||||
|
public ServiceInstanceListSupplier polarisRouterDiscoveryClientServiceInstanceListSupplier(RouterAPI routerAPI,
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
return new PolarisRouterServiceInstanceListSupplier(
|
||||||
|
ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().build(context), routerAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,63 +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.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.IPing;
|
|
||||||
import com.netflix.loadbalancer.IRule;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.netflix.loadbalancer.ServerList;
|
|
||||||
import com.tencent.cloud.polaris.router.PolarisRoutingLoadBalancer;
|
|
||||||
import com.tencent.cloud.polaris.router.rule.PolarisLoadBalanceRule;
|
|
||||||
import com.tencent.cloud.polaris.router.rule.PolarisWeightedRandomRule;
|
|
||||||
import com.tencent.polaris.router.api.core.RouterAPI;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration of ribbon client of Polaris.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class PolarisRibbonClientConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public IRule polarisRibbonRule(PolarisRibbonProperties polarisRibbonProperties) {
|
|
||||||
switch (PolarisLoadBalanceRule
|
|
||||||
.fromStrategy(polarisRibbonProperties.getStrategy())) {
|
|
||||||
case WEIGHTED_RANDOM_RULE:
|
|
||||||
default:
|
|
||||||
return new PolarisWeightedRandomRule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public ILoadBalancer polarisRoutingLoadBalancer(IClientConfig iClientConfig,
|
|
||||||
IRule iRule, IPing iPing, ServerList<Server> serverList,
|
|
||||||
RouterAPI polarisRouter) {
|
|
||||||
return new PolarisRoutingLoadBalancer(iClientConfig, iRule, iPing, serverList,
|
|
||||||
polarisRouter);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,52 +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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load balance rule.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public enum PolarisLoadBalanceRule {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weighted random load balance rule.
|
|
||||||
*/
|
|
||||||
WEIGHTED_RANDOM_RULE("weighted_random");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load balance strategy.
|
|
||||||
*/
|
|
||||||
final 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPolicy() {
|
|
||||||
return policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,73 +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.List;
|
|
||||||
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.tencent.cloud.common.pojo.PolarisServer;
|
|
||||||
import com.tencent.polaris.api.config.consumer.LoadBalanceConfig;
|
|
||||||
import com.tencent.polaris.api.pojo.Instance;
|
|
||||||
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.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Weighted random load balance strategy.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class PolarisWeightedRandomRule extends AbstractLoadBalancerRule {
|
|
||||||
|
|
||||||
private static final String POLICY = LoadBalanceConfig.LOAD_BALANCE_WEIGHTED_RANDOM;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RouterAPI polarisRouter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initWithNiwsConfig(IClientConfig clientConfig) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Server choose(Object key) {
|
|
||||||
List<Server> allServers = getLoadBalancer().getReachableServers();
|
|
||||||
if (CollectionUtils.isEmpty(allServers)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Server server = allServers.get(0);
|
|
||||||
if (!(server instanceof PolarisServer)) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"PolarisDiscoveryRule only support PolarisServer instances");
|
|
||||||
}
|
|
||||||
PolarisServer polarisServer = (PolarisServer) server;
|
|
||||||
ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest();
|
|
||||||
request.setDstInstances(polarisServer.getServiceInstances());
|
|
||||||
request.setLbPolicy(POLICY);
|
|
||||||
ProcessLoadBalanceResponse processLoadBalanceResponse = polarisRouter
|
|
||||||
.processLoadBalance(request);
|
|
||||||
Instance targetInstance = processLoadBalanceResponse.getTargetInstance();
|
|
||||||
return new PolarisServer(polarisServer.getServiceInstances(), targetInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,2 +1,2 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
com.tencent.cloud.polaris.router.config.PolarisRibbonAutoConfiguration
|
com.tencent.cloud.polaris.router.config.PolarisLoadBalancerAutoConfiguration
|
||||||
|
@ -1,62 +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.cloud.polaris.context.PolarisContextConfiguration;
|
|
||||||
import com.tencent.polaris.router.api.core.RouterAPI;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import static com.tencent.polaris.test.common.Consts.PORT;
|
|
||||||
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for {@link PolarisRibbonAutoConfiguration}
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class PolarisRibbonAutoConfigurationTest {
|
|
||||||
|
|
||||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(PolarisRibbonTest.class,
|
|
||||||
PolarisRibbonAutoConfiguration.class,
|
|
||||||
PolarisContextConfiguration.class))
|
|
||||||
.withPropertyValues("spring.application.name=" + SERVICE_PROVIDER)
|
|
||||||
.withPropertyValues("server.port=" + PORT)
|
|
||||||
.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(PolarisRibbonProperties.class);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
static class PolarisRibbonTest {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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.cloud.polaris.context.PolarisContextConfiguration;
|
||||||
|
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
|
||||||
|
import com.tencent.polaris.router.api.core.RouterAPI;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link PolarisLoadBalancerAutoConfiguration}
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class PolarisRouterAutoConfigurationTest {
|
||||||
|
|
||||||
|
private final ApplicationContextRunner blockingContextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(PolarisLoadBalancerTest.class, PolarisContextConfiguration.class,
|
||||||
|
PolarisLoadBalancerAutoConfiguration.class,
|
||||||
|
PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class))
|
||||||
|
.withPropertyValues("spring.cloud.loadbalancer.configurations=polaris");
|
||||||
|
|
||||||
|
private final ApplicationContextRunner noPolarisContextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(PolarisLoadBalancerTest.class, PolarisContextConfiguration.class,
|
||||||
|
PolarisLoadBalancerAutoConfiguration.class,
|
||||||
|
PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for BlockingDiscovery.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void test1() {
|
||||||
|
this.blockingContextRunner.run(context -> {
|
||||||
|
assertThat(context).hasSingleBean(RouterAPI.class);
|
||||||
|
assertThat(context).hasSingleBean(PolarisLoadBalancerProperties.class);
|
||||||
|
assertThat(context)
|
||||||
|
.doesNotHaveBean(PolarisLoadBalancerClientConfiguration.PolarisReactiveSupportConfiguration.class);
|
||||||
|
assertThat(context)
|
||||||
|
.hasSingleBean(PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class);
|
||||||
|
assertThat(context).doesNotHaveBean(PolarisRouterServiceInstanceListSupplier.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for no Polaris.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void test2() {
|
||||||
|
this.noPolarisContextRunner.run(context -> {
|
||||||
|
assertThat(context).hasSingleBean(RouterAPI.class);
|
||||||
|
assertThat(context).hasSingleBean(PolarisLoadBalancerProperties.class);
|
||||||
|
assertThat(context)
|
||||||
|
.doesNotHaveBean(PolarisLoadBalancerClientConfiguration.PolarisReactiveSupportConfiguration.class);
|
||||||
|
assertThat(context)
|
||||||
|
.hasSingleBean(PolarisLoadBalancerClientConfiguration.PolarisBlockingSupportConfiguration.class);
|
||||||
|
assertThat(context).doesNotHaveBean(PolarisRouterServiceInstanceListSupplier.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
static class PolarisLoadBalancerTest {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,70 +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.common.metadata.filter.gateway;
|
|
||||||
|
|
||||||
import com.netflix.zuul.ZuulFilter;
|
|
||||||
import com.netflix.zuul.context.RequestContext;
|
|
||||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContext;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContextHolder;
|
|
||||||
|
|
||||||
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.REQUEST_URI_KEY;
|
|
||||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zuul output first filter used for setting peer info in context.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class MetadataFirstZuulFilter extends ZuulFilter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String filterType() {
|
|
||||||
return PRE_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int filterOrder() {
|
|
||||||
return PRE_DECORATION_FILTER_ORDER + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldFilter() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object run() {
|
|
||||||
// get request context
|
|
||||||
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
||||||
|
|
||||||
// TODO The peer namespace is temporarily the same as the local namespace
|
|
||||||
MetadataContextHolder.get().putSystemMetadata(
|
|
||||||
MetadataConstant.SystemMetadataKey.PEER_NAMESPACE,
|
|
||||||
MetadataContext.LOCAL_NAMESPACE);
|
|
||||||
MetadataContextHolder.get().putSystemMetadata(
|
|
||||||
MetadataConstant.SystemMetadataKey.PEER_SERVICE,
|
|
||||||
(String) requestContext.get(SERVICE_ID_KEY));
|
|
||||||
MetadataContextHolder.get().putSystemMetadata(
|
|
||||||
MetadataConstant.SystemMetadataKey.PEER_PATH,
|
|
||||||
(String) requestContext.get(REQUEST_URI_KEY));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,111 +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.common.pojo;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.tencent.polaris.api.pojo.Instance;
|
|
||||||
import com.tencent.polaris.api.pojo.ServiceInstances;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Polaris' implementation of {@link Server}.
|
|
||||||
*
|
|
||||||
* @author Haotian Zhang
|
|
||||||
*/
|
|
||||||
public class PolarisServer extends Server {
|
|
||||||
|
|
||||||
private final ServiceInstances serviceInstances;
|
|
||||||
|
|
||||||
private final Instance instance;
|
|
||||||
|
|
||||||
private final MetaInfo metaInfo;
|
|
||||||
|
|
||||||
public PolarisServer(ServiceInstances serviceInstances, Instance instance) {
|
|
||||||
super(instance.getHost(), instance.getPort());
|
|
||||||
if (StringUtils.equalsIgnoreCase(instance.getProtocol(), "https")) {
|
|
||||||
setSchemea("https");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setSchemea("http");
|
|
||||||
}
|
|
||||||
this.serviceInstances = serviceInstances;
|
|
||||||
this.instance = instance;
|
|
||||||
this.metaInfo = new MetaInfo() {
|
|
||||||
@Override
|
|
||||||
public String getAppName() {
|
|
||||||
return instance.getService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerGroup() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServiceIdForDiscovery() {
|
|
||||||
return instance.getService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getInstanceId() {
|
|
||||||
return instance.getId();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instance getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaInfo getMetaInfo() {
|
|
||||||
return metaInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getMetadata() {
|
|
||||||
return instance.getMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!super.equals(o)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PolarisServer that = (PolarisServer) o;
|
|
||||||
return Objects.equals(instance, that.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(super.hashCode(), instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceInstances getServiceInstances() {
|
|
||||||
return serviceInstances;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue