init
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package org.dromara.common.loadbalance.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
/**
|
||||
* dubbo自定义负载均衡配置注入
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
System.setProperty("dubbo.consumer.loadbalance", "customDubboLoadBalancer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package org.dromara.common.loadbalance.config;
|
||||
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
|
||||
/**
|
||||
* 自定义负载均衡自动配置
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@LoadBalancerClients(defaultConfiguration = CustomLoadBalanceClientConfiguration.class)
|
||||
public class CustomLoadBalanceAutoConfiguration {
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package org.dromara.common.loadbalance.config;
|
||||
|
||||
import org.dromara.common.loadbalance.core.CustomSpringCloudLoadBalancer;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
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.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* 自定义负载均衡客户端配置
|
||||
*
|
||||
* @author LionLi
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class CustomLoadBalanceClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(LoadBalancerClientFactory.class)
|
||||
public ReactorLoadBalancer<ServiceInstance> customLoadBalancer(Environment environment,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
|
||||
return new CustomSpringCloudLoadBalancer(name,
|
||||
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class));
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package org.dromara.common.loadbalance.core;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 自定义 Dubbo 负载均衡算法
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
public class CustomDubboLoadBalancer extends AbstractLoadBalance {
|
||||
|
||||
@Override
|
||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (NetUtil.localIpv4s().contains(invoker.getUrl().getHost())) {
|
||||
return invoker;
|
||||
}
|
||||
}
|
||||
return invokers.get(ThreadLocalRandom.current().nextInt(invokers.size()));
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package org.dromara.common.loadbalance.core;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.SelectedInstanceCallback;
|
||||
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 自定义 SpringCloud 负载均衡算法
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class CustomSpringCloudLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
||||
|
||||
private final String serviceId;
|
||||
|
||||
private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
|
||||
|
||||
@Override
|
||||
public Mono<Response<ServiceInstance>> choose(Request request) {
|
||||
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
|
||||
return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
|
||||
}
|
||||
|
||||
private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);
|
||||
if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
|
||||
((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
|
||||
}
|
||||
return serviceInstanceResponse;
|
||||
}
|
||||
|
||||
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
|
||||
if (instances.isEmpty()) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("No servers available for service: " + serviceId);
|
||||
}
|
||||
return new EmptyResponse();
|
||||
}
|
||||
for (ServiceInstance instance : instances) {
|
||||
if (NetUtil.localIpv4s().contains(instance.getHost())) {
|
||||
return new DefaultResponse(instance);
|
||||
}
|
||||
}
|
||||
return new DefaultResponse(instances.get(ThreadLocalRandom.current().nextInt(instances.size())));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
customDubboLoadBalancer=org.dromara.common.loadbalance.core.CustomDubboLoadBalancer
|
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||
org.dromara.common.loadbalance.config.CustomEnvironmentPostProcessor
|
@@ -0,0 +1 @@
|
||||
org.dromara.common.loadbalance.config.CustomLoadBalanceAutoConfiguration
|
Reference in New Issue
Block a user