自定义负载均衡类
java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
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 org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;
import java.util.List;
/**
* 参照 org.springframework.cloud.loadbalancer.core.RandomLoadBalancer RoundRobinLoadBalancer
*
* @author 向振华
* @date 2025/03/28 15:54
*/
public class MyLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final Log log = LogFactory.getLog(MyLoadBalancer.class);
private final String serviceId;
private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
public MyLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
this.serviceId = serviceId;
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
}
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get(request).next().map((serviceInstances) -> {
return this.processInstanceResponse(request, supplier, serviceInstances);
});
}
private Response<ServiceInstance> processInstanceResponse(Request request, ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances) {
Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(request, serviceInstances);
if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
}
return serviceInstanceResponse;
}
private Response<ServiceInstance> getInstanceResponse(Request request, List<ServiceInstance> instances) {
if (instances.isEmpty()) {
log.error("No servers available for service: " + serviceId);
return new EmptyResponse();
} else {
// 最终在这里选择服务
// 这里自定义规则是根据请求头传的索引选择服务
RequestDataContext context = (RequestDataContext) request.getContext();
HttpHeaders headers = context.getClientRequest().getHeaders();
String i = headers.getFirst("choose-index");
ServiceInstance instance = instances.get(Integer.parseInt(i));
return new DefaultResponse(instance);
}
}
}
配置类
java
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.core.env.Environment;
/**
* @author 向振华
* @date 2025/03/28 16:49
*/
public class MyLoadBalancerConfig {
public MyLoadBalancerConfig() {
}
@Bean
public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty("loadbalancer.client.name");
return new MyLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
然后在启动类加上注解,多个微服务在数组继续添加@LoadBalancerClient
java
@LoadBalancerClients({
@LoadBalancerClient(name = "my-service", configuration = MyLoadBalancerConfig.class)
})
或者在引用的客户端类@FeignClient处,加@LoadBalancerClient
java
@LoadBalancerClient(name = "my-service",configuration = MyLoadBalancerConfig.class)