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