Merge pull request #2152 from XuDaojie/nacos-loadbalancer-2020.0.0
Nacos loadbalancer prpull/2301/head
commit
a064331b88
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.cloud.nacos.balancer;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
|
import com.alibaba.nacos.client.naming.core.Balancer;
|
||||||
|
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author itmuch.com XuDaojie
|
||||||
|
* @since 2021.1
|
||||||
|
*/
|
||||||
|
public class NacosBalancer extends Balancer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Choose instance by weight.
|
||||||
|
* @param instances Instance List
|
||||||
|
* @return the chosen instance
|
||||||
|
*/
|
||||||
|
public static Instance getHostByRandomWeight2(List<Instance> instances) {
|
||||||
|
return getHostByRandomWeight(instances);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring Cloud LoadBalancer Choose instance by weight.
|
||||||
|
* @param serviceInstances Instance List
|
||||||
|
* @return the chosen instance
|
||||||
|
*/
|
||||||
|
public static ServiceInstance getHostByRandomWeight3(
|
||||||
|
List<ServiceInstance> serviceInstances) {
|
||||||
|
Map<Instance, ServiceInstance> instanceMap = new HashMap<>();
|
||||||
|
List<Instance> nacosInstance = serviceInstances.stream().map(serviceInstance -> {
|
||||||
|
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||||
|
|
||||||
|
// see
|
||||||
|
// com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery.hostToServiceInstance()
|
||||||
|
Instance instance = new Instance();
|
||||||
|
instance.setIp(serviceInstance.getHost());
|
||||||
|
instance.setPort(serviceInstance.getPort());
|
||||||
|
instance.setWeight(Double.parseDouble(metadata.get("nacos.weight")));
|
||||||
|
instance.setHealthy(Boolean.parseBoolean(metadata.get("nacos.healthy")));
|
||||||
|
instanceMap.put(instance, serviceInstance);
|
||||||
|
return instance;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Instance instance = getHostByRandomWeight2(nacosInstance);
|
||||||
|
return instanceMap.get(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.cloud.nacos.loadbalancer;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.nacos.enabled", havingValue = "true")
|
||||||
|
public @interface ConditionalOnLoadBalancerNacos {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.cloud.nacos.loadbalancer;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||||
|
* Auto-configuration} that sets up LoadBalancer for Nacos.
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ConditionalOnLoadBalancerNacos
|
||||||
|
@ConditionalOnNacosDiscoveryEnabled
|
||||||
|
@LoadBalancerClients(defaultConfiguration = NacosLoadBalancerClientConfiguration.class)
|
||||||
|
public class LoadBalancerNacosAutoConfiguration {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.cloud.nacos.loadbalancer;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ServiceInstanceListSupplier} don't use cache.<br>
|
||||||
|
* <br>
|
||||||
|
* 1. LoadBalancerCache causes information such as the weight of the service instance to
|
||||||
|
* be changed without immediate effect.<br>
|
||||||
|
* 2. Nacos itself supports caching.
|
||||||
|
*
|
||||||
|
* @author XuDaojie
|
||||||
|
* @since 2021.1
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnDiscoveryEnabled
|
||||||
|
public class NacosLoadBalancerClientConfiguration {
|
||||||
|
|
||||||
|
private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 183827465;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
|
||||||
|
LoadBalancerClientFactory loadBalancerClientFactory,
|
||||||
|
NacosDiscoveryProperties nacosDiscoveryProperties) {
|
||||||
|
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
|
||||||
|
return new NacosLoadBalancer(
|
||||||
|
loadBalancerClientFactory.getLazyProvider(name,
|
||||||
|
ServiceInstanceListSupplier.class),
|
||||||
|
name, nacosDiscoveryProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnReactiveDiscoveryEnabled
|
||||||
|
@Order(REACTIVE_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(ReactiveDiscoveryClient.class)
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference")
|
||||||
|
public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
return ServiceInstanceListSupplier.builder().withDiscoveryClient()
|
||||||
|
.withZonePreference().build(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnBlockingDiscoveryEnabled
|
||||||
|
@Order(REACTIVE_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(DiscoveryClient.class)
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference")
|
||||||
|
public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient()
|
||||||
|
.withZonePreference().build(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue