support near by router (#196)

pull/201/head
lepdou 3 years ago committed by GitHub
parent 9378bb2878
commit dc77ec0bec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,6 @@
- [Add metadata transfer example.](https://github.com/Tencent/spring-cloud-tencent/pull/184)
- [Feature: Support metadata router.](https://github.com/Tencent/spring-cloud-tencent/pull/191)
- [Feature: Misc optimize metadata router.](https://github.com/Tencent/spring-cloud-tencent/pull/192)
- [Feature:Support near by router.](https://github.com/Tencent/spring-cloud-tencent/pull/196)
- [Feature: Load application.yml and application-${profile}.yml from polaris server.](https://github.com/Tencent/spring-cloud-tencent/pull/199)
- [feat:add rate limit of unirate.](https://github.com/Tencent/spring-cloud-tencent/pull/197)

@ -18,6 +18,8 @@
package com.tencent.cloud.polaris.registry;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -95,10 +97,13 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
instanceRegisterRequest.setPort(registration.getPort());
instanceRegisterRequest.setWeight(polarisDiscoveryProperties.getWeight());
instanceRegisterRequest.setToken(polarisDiscoveryProperties.getToken());
instanceRegisterRequest.setRegion(staticMetadataManager.getRegion());
instanceRegisterRequest.setZone(staticMetadataManager.getZone());
instanceRegisterRequest.setCampus(staticMetadataManager.getCampus());
if (null != heartbeatExecutor) {
instanceRegisterRequest.setTtl(ttl);
}
instanceRegisterRequest.setMetadata(staticMetadataManager.getMergedStaticMetadata());
instanceRegisterRequest.setMetadata(getInstanceMetadata());
instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion());
try {
@ -123,6 +128,16 @@ public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
}
}
private Map<String, String> getInstanceMetadata() {
Map<String, String> metadata = new HashMap<>();
metadata.putAll(staticMetadataManager.getMergedStaticMetadata());
// location info will be putted both in metadata and instance's field
metadata.putAll(staticMetadataManager.getLocationMetadata());
return metadata;
}
@Override
public void deregister(Registration registration) {

@ -34,6 +34,10 @@
<groupId>com.tencent.polaris</groupId>
<artifactId>router-metadata</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>router-nearby</artifactId>
</dependency>
<!-- Polaris dependencies end -->
<dependency>

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.router;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -39,14 +40,18 @@ import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils;
import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties;
import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties;
import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInfo;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.plugins.router.metadata.MetadataRouter;
import com.tencent.polaris.plugins.router.nearby.NearbyRouter;
import com.tencent.polaris.plugins.router.rule.RuleBasedRouter;
import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest;
import com.tencent.polaris.router.api.rpc.ProcessRoutersResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;
@ -76,14 +81,24 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
private final static String STRATEGY_AVAILABILITY_FILTERING = "availabilityFilteringRule";
private final PolarisLoadBalancerProperties loadBalancerProperties;
private final PolarisNearByRouterProperties polarisNearByRouterProperties;
private final PolarisMetadataRouterProperties polarisMetadataRouterProperties;
private final PolarisRuleBasedRouterProperties polarisRuleBasedRouterProperties;
private final RouterAPI routerAPI;
private final AbstractLoadBalancerRule delegateRule;
public PolarisLoadBalancerCompositeRule(RouterAPI routerAPI, PolarisLoadBalancerProperties polarisLoadBalancerProperties,
public PolarisLoadBalancerCompositeRule(RouterAPI routerAPI,
PolarisLoadBalancerProperties polarisLoadBalancerProperties,
PolarisNearByRouterProperties polarisNearByRouterProperties,
PolarisMetadataRouterProperties polarisMetadataRouterProperties,
PolarisRuleBasedRouterProperties polarisRuleBasedRouterProperties,
IClientConfig iClientConfig) {
this.routerAPI = routerAPI;
this.polarisNearByRouterProperties = polarisNearByRouterProperties;
this.loadBalancerProperties = polarisLoadBalancerProperties;
this.polarisMetadataRouterProperties = polarisMetadataRouterProperties;
this.polarisRuleBasedRouterProperties = polarisRuleBasedRouterProperties;
delegateRule = getRule();
delegateRule.initWithNiwsConfig(iClientConfig);
@ -134,21 +149,40 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
ProcessRoutersRequest processRoutersRequest = new ProcessRoutersRequest();
processRoutersRequest.setDstInstances(serviceInstances);
Map<String, String> transitiveLabels = getRouterLabels(key, PolarisRouterContext.TRANSITIVE_LABELS);
processRoutersRequest.putRouterMetadata(MetadataRouter.ROUTER_TYPE_METADATA, transitiveLabels);
// metadata router
if (polarisMetadataRouterProperties.isEnabled()) {
Map<String, String> transitiveLabels = getRouterLabels(key, PolarisRouterContext.TRANSITIVE_LABELS);
processRoutersRequest.putRouterMetadata(MetadataRouter.ROUTER_TYPE_METADATA, transitiveLabels);
}
// nearby router
if (polarisNearByRouterProperties.isEnabled()) {
Map<String, String> nearbyRouterMetadata = new HashMap<>();
nearbyRouterMetadata.put(NearbyRouter.ROUTER_ENABLED, "true");
processRoutersRequest.putRouterMetadata(NearbyRouter.ROUTER_TYPE_NEAR_BY, nearbyRouterMetadata);
}
String srcNamespace = MetadataContext.LOCAL_NAMESPACE;
String srcService = MetadataContext.LOCAL_SERVICE;
// rule based router
// set dynamic switch for rule based router
boolean ruleBasedRouterEnabled = polarisRuleBasedRouterProperties.isEnabled();
Map<String, String> ruleRouterMetadata = new HashMap<>();
ruleRouterMetadata.put(RuleBasedRouter.ROUTER_ENABLED, String.valueOf(ruleBasedRouterEnabled));
processRoutersRequest.putRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED, ruleRouterMetadata);
if (StringUtils.isNotBlank(srcNamespace) && StringUtils.isNotBlank(srcService)) {
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setNamespace(srcNamespace);
serviceInfo.setService(srcService);
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setNamespace(MetadataContext.LOCAL_NAMESPACE);
serviceInfo.setService(MetadataContext.LOCAL_SERVICE);
if (ruleBasedRouterEnabled) {
Map<String, String> ruleRouterLabels = getRouterLabels(key, PolarisRouterContext.RULE_ROUTER_LABELS);
// The label information that the rule based routing depends on
// is placed in the metadata of the source service for transmission.
// Later, can consider putting it in routerMetadata like other routers.
serviceInfo.setMetadata(ruleRouterLabels);
processRoutersRequest.setSourceService(serviceInfo);
}
processRoutersRequest.setSourceService(serviceInfo);
return processRoutersRequest;
}

@ -0,0 +1,46 @@
/*
* 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.boot.context.properties.ConfigurationProperties;
/**
* the configuration for metadata router.
* @author lepdou 2022-05-23
*/
@ConfigurationProperties(prefix = "spring.cloud.polaris.router.metadata-router")
public class PolarisMetadataRouterProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "PolarisMetadataRouterProperties{" +
"enabled=" + enabled +
'}';
}
}

@ -0,0 +1,47 @@
/*
* 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.boot.context.properties.ConfigurationProperties;
/**
* the configuration for nearby router.
*
* @author lepdou 2022-05-23
*/
@ConfigurationProperties(prefix = "spring.cloud.polaris.router.nearby-router")
public class PolarisNearByRouterProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "PolarisNearByRouterProperties{" +
"enabled=" + enabled +
'}';
}
}

@ -0,0 +1,48 @@
/*
* 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.boot.context.properties.ConfigurationProperties;
/**
* the configuration for rule based router.
*
* @author lepdou 2022-05-23
*/
@ConfigurationProperties(prefix = "spring.cloud.polaris.router.rule-router")
public class PolarisRuleBasedRouterProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "PolarisNearByRouterProperties{" +
"enabled=" + enabled +
'}';
}
}

@ -37,7 +37,12 @@ public class RibbonConfiguration {
@Bean
public IRule polarisLoadBalancerCompositeRule(RouterAPI routerAPI,
PolarisLoadBalancerProperties polarisLoadBalancerProperties,
PolarisNearByRouterProperties polarisNearByRouterProperties,
PolarisMetadataRouterProperties polarisMetadataRouterProperties,
PolarisRuleBasedRouterProperties polarisRuleBasedRouterProperties,
IClientConfig iClientConfig) {
return new PolarisLoadBalancerCompositeRule(routerAPI, polarisLoadBalancerProperties, iClientConfig);
return new PolarisLoadBalancerCompositeRule(routerAPI, polarisLoadBalancerProperties,
polarisNearByRouterProperties, polarisMetadataRouterProperties,
polarisRuleBasedRouterProperties, iClientConfig);
}
}

@ -32,6 +32,7 @@ import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.lang.Nullable;
@ -44,6 +45,7 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
*/
@Configuration
@RibbonClients(defaultConfiguration = {FeignConfiguration.class, RibbonConfiguration.class})
@Import({PolarisNearByRouterProperties.class, PolarisMetadataRouterProperties.class, PolarisRuleBasedRouterProperties.class})
public class RouterAutoConfiguration {
@Bean

@ -0,0 +1,22 @@
{
"properties": [
{
"name": "spring.cloud.polaris.router.metadata-router.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "the switch for metadata router."
},
{
"name": "spring.cloud.polaris.router.nearby-router.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "the switch for near by router."
},
{
"name": "spring.cloud.polaris.router.rule-router.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "the switch for rule based router."
}
]
}

@ -58,6 +58,12 @@ public class MetadataContext {
namespace = ApplicationContextAwareUtils
.getProperties("spring.cloud.polaris.discovery.namespace", "default");
}
if (StringUtils.isEmpty(namespace)) {
throw new RuntimeException("namespace should not be blank. please configure spring.cloud.polaris.namespace or "
+ "spring.cloud.polaris.discovery.namespace");
}
LOCAL_NAMESPACE = namespace;
String serviceName = ApplicationContextAwareUtils
@ -67,6 +73,11 @@ public class MetadataContext {
"spring.cloud.polaris.discovery.service", ApplicationContextAwareUtils
.getProperties("spring.application.name", null));
}
if (StringUtils.isEmpty(serviceName)) {
throw new RuntimeException("service name should not be blank. please configure spring.cloud.polaris.service or "
+ "spring.cloud.polaris.discovery.service or spring.application.name");
}
LOCAL_SERVICE = serviceName;
}

@ -39,6 +39,13 @@ public class StaticMetadataManager {
private static final String ENV_METADATA_PREFIX = "SCT_METADATA_CONTENT_";
private static final int ENV_METADATA_PREFIX_LENGTH = ENV_METADATA_PREFIX.length();
private static final String ENV_METADATA_CONTENT_TRANSITIVE = "SCT_METADATA_CONTENT_TRANSITIVE";
private static final String ENV_METADATA_ZONE = "SCT_METADATA_ZONE";
private static final String ENV_METADATA_REGION = "SCT_METADATA_REGION";
private static final String ENV_METADATA_CAMPUS = "SCT_METADATA_CAMPUS";
private static final String LOCATION_KEY_REGION = "region";
private static final String LOCATION_KEY_ZONE = "zone";
private static final String LOCATION_KEY_CAMPUS = "campus";
private Map<String, String> envMetadata;
private Map<String, String> envTransitiveMetadata;
@ -46,11 +53,17 @@ public class StaticMetadataManager {
private Map<String, String> configTransitiveMetadata;
private Map<String, String> mergedStaticMetadata;
private Map<String, String> mergedStaticTransitiveMetadata;
private String zone;
private String region;
private String campus;
public StaticMetadataManager(MetadataLocalProperties metadataLocalProperties) {
parseConfigMetadata(metadataLocalProperties);
parseEnvMetadata();
merge();
parseLocationMetadata();
LOGGER.info("[SCT] Loaded static metadata info. {}", this);
}
private void parseEnvMetadata() {
@ -119,6 +132,12 @@ public class StaticMetadataManager {
this.mergedStaticTransitiveMetadata = Collections.unmodifiableMap(mergedTransitiveMetadataResult);
}
private void parseLocationMetadata() {
zone = System.getenv(ENV_METADATA_ZONE);
region = System.getenv(ENV_METADATA_REGION);
campus = System.getenv(ENV_METADATA_CAMPUS);
}
public Map<String, String> getAllEnvMetadata() {
return envMetadata;
}
@ -139,7 +158,48 @@ public class StaticMetadataManager {
return mergedStaticMetadata;
}
Map<String, String> getMergedStaticTransitiveMetadata() {
public Map<String, String> getMergedStaticTransitiveMetadata() {
return mergedStaticTransitiveMetadata;
}
public String getZone() {
return zone;
}
public String getRegion() {
return region;
}
public String getCampus() {
return campus;
}
public Map<String, String> getLocationMetadata() {
Map<String, String> locationMetadata = new HashMap<>();
if (StringUtils.isNotBlank(region)) {
locationMetadata.put(LOCATION_KEY_REGION, region);
}
if (StringUtils.isNotBlank(zone)) {
locationMetadata.put(LOCATION_KEY_ZONE, zone);
}
if (StringUtils.isNotBlank(campus)) {
locationMetadata.put(LOCATION_KEY_CAMPUS, campus);
}
return locationMetadata;
}
@Override
public String toString() {
return "StaticMetadataManager{" +
"envMetadata=" + envMetadata +
", envTransitiveMetadata=" + envTransitiveMetadata +
", configMetadata=" + configMetadata +
", configTransitiveMetadata=" + configTransitiveMetadata +
", mergedStaticMetadata=" + mergedStaticMetadata +
", mergedStaticTransitiveMetadata=" + mergedStaticTransitiveMetadata +
", zone='" + zone + '\'' +
", region='" + region + '\'' +
", campus='" + campus + '\'' +
'}';
}
}

@ -18,9 +18,15 @@
package com.tencent.cloud.polaris.context;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.metadata.config.MetadataAutoConfiguration;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.plugin.common.ValueContext;
import com.tencent.polaris.api.plugin.route.LocationLevel;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -31,14 +37,33 @@ import org.springframework.context.annotation.Bean;
* @author Haotian Zhang
*/
@ConditionalOnPolarisEnabled
@EnableConfigurationProperties({ PolarisContextProperties.class })
@EnableConfigurationProperties({PolarisContextProperties.class})
@ImportAutoConfiguration(MetadataAutoConfiguration.class)
public class PolarisContextAutoConfiguration {
@Bean(name = "polarisContext", initMethod = "init", destroyMethod = "destroy")
@ConditionalOnMissingBean
public SDKContext polarisContext(PolarisContextProperties properties)
public SDKContext polarisContext(PolarisContextProperties properties, StaticMetadataManager staticMetadataManager)
throws PolarisException {
return SDKContext.initContextByConfig(properties.configuration());
SDKContext sdkContext = SDKContext.initContextByConfig(properties.configuration());
// init current instance location info from environment
ValueContext valueContext = sdkContext.getValueContext();
String region = staticMetadataManager.getRegion();
String zone = staticMetadataManager.getZone();
String campus = staticMetadataManager.getCampus();
if (StringUtils.isNotBlank(region)) {
valueContext.setValue(LocationLevel.region.name(), region);
}
if (StringUtils.isNotBlank(zone)) {
valueContext.setValue(LocationLevel.zone.name(), zone);
}
if (StringUtils.isNotBlank(campus)) {
valueContext.setValue(LocationLevel.campus.name(), campus);
}
return sdkContext;
}
@Bean

Loading…
Cancel
Save