This commit is contained in:
2025-06-17 17:08:14 +08:00
commit 71179324c8
1205 changed files with 798946 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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));
}
}

View File

@@ -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()));
}
}

View File

@@ -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())));
}
}

View File

@@ -0,0 +1 @@
customDubboLoadBalancer=org.dromara.common.loadbalance.core.CustomDubboLoadBalancer

View File

@@ -0,0 +1,2 @@
org.springframework.boot.env.EnvironmentPostProcessor=\
org.dromara.common.loadbalance.config.CustomEnvironmentPostProcessor

View File

@@ -0,0 +1 @@
org.dromara.common.loadbalance.config.CustomLoadBalanceAutoConfiguration