
com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancer Maven / Gradle / Ivy
/*
* 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.loadbalancer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.PollingServerListUpdater;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.loadbalancer.transformer.InstanceTransformer;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.DefaultInstance;
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.GetHealthyInstancesRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;
/**
* Routing load balancer of polaris.
*
* @author Haotian Zhang
*/
public class PolarisLoadBalancer extends DynamicServerListLoadBalancer {
private static final ThreadLocal> THREAD_CACHE_SERVERS = new ThreadLocal<>();
private final ConsumerAPI consumerAPI;
private final PolarisLoadBalancerProperties polarisLoadBalancerProperties;
private final InstanceTransformer instanceTransformer;
public PolarisLoadBalancer(IClientConfig config, IRule rule, IPing ping, ServerList serverList,
ConsumerAPI consumerAPI, PolarisLoadBalancerProperties properties, InstanceTransformer instanceTransformer) {
super(config, rule, ping, serverList, null, new PollingServerListUpdater());
this.consumerAPI = consumerAPI;
this.polarisLoadBalancerProperties = properties;
this.instanceTransformer = instanceTransformer;
}
@Override
public void addServers(List servers) {
THREAD_CACHE_SERVERS.set(servers);
}
@Override
public List getReachableServers() {
// Get servers first from the thread context. When routers filter all instances, getReachableServersWithoutCache function cannot be executed.
if (THREAD_CACHE_SERVERS.get() != null) {
return THREAD_CACHE_SERVERS.get();
}
return getReachableServersWithoutCache();
}
public List getReachableServersWithoutCache() {
ServiceInstances serviceInstances;
if (polarisLoadBalancerProperties.getDiscoveryType().equals(ContextConstant.POLARIS)) {
serviceInstances = getPolarisDiscoveryServiceInstances();
}
else {
serviceInstances = getExtendDiscoveryServiceInstances();
}
if (serviceInstances == null || CollectionUtils.isEmpty(serviceInstances.getInstances())) {
return Collections.emptyList();
}
List servers = new LinkedList<>();
for (Instance instance : serviceInstances.getInstances()) {
servers.add(new PolarisServer(serviceInstances, instance));
}
return servers;
}
private ServiceInstances getPolarisDiscoveryServiceInstances() {
return getAllInstances(MetadataContext.LOCAL_NAMESPACE, name).toServiceInstances();
}
private ServiceInstances getExtendDiscoveryServiceInstances() {
List allServers = super.getAllServers();
if (CollectionUtils.isEmpty(allServers)) {
return null;
}
ServiceInstances serviceInstances;
if (StringUtils.isBlank(name)) {
throw new IllegalStateException(
"PolarisLoadBalancer only Server with AppName or ServiceIdForDiscovery attribute");
}
ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, name);
List instances = new ArrayList<>(8);
for (Server server : allServers) {
DefaultInstance instance = new DefaultInstance();
instance.setNamespace(MetadataContext.LOCAL_NAMESPACE);
instance.setService(name);
instance.setHealthy(server.isAlive());
instance.setProtocol(server.getScheme());
instance.setId(server.getId());
instance.setHost(server.getHost());
instance.setPort(server.getPort());
instance.setZone(server.getZone());
instance.setWeight(100);
if (instanceTransformer != null) {
instanceTransformer.transformCustom(instance, server);
}
instances.add(instance);
}
serviceInstances = new DefaultServiceInstances(serviceKey, instances);
return serviceInstances;
}
@Override
public List getAllServers() {
return getReachableServers();
}
/**
* Get a list of instances.
* @param namespace namespace
* @param serviceName service name
* @return list of instances
*/
public InstancesResponse getAllInstances(String namespace, String serviceName) {
GetHealthyInstancesRequest request = new GetHealthyInstancesRequest();
request.setNamespace(namespace);
request.setService(serviceName);
request.setIncludeCircuitBreakInstances(false);
return consumerAPI.getHealthyInstances(request);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy