当前位置: 首页 > news >正文

Spring Cloud ReactorServiceInstanceLoadBalancer 自定义负载均衡

自定义负载均衡类

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

配置类

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

@LoadBalancerClients({
        @LoadBalancerClient(name = "my-service", configuration = MyLoadBalancerConfig.class)
})

或者在引用的客户端类@FeignClient处,加@LoadBalancerClient

@LoadBalancerClient(name = "my-service",configuration = MyLoadBalancerConfig.class)

相关文章:

  • Codeforces Round 1013 (Div. 3)-F
  • 信息系统项目管理师知识体系
  • 0328-内存图2
  • 并发编程--共享内存SHM
  • OpenGL —— 基于Qt的视频播放器 - ffmpeg硬解码,QOpenGL渲染yuv420p或nv12视频(附源码)
  • Windows10上部署DeepSeek R1保姆式操作详解(ollama方式+ChatBox)
  • 解决PLC通信会断然后报错的问题
  • 金融级密码管理器——生物特征密钥绑定方案
  • python算法:leetcode二叉树相关算法题
  • 搭建Flutter开发环境 - MacOs
  • Django项目之订单管理part6(message组件和组合搜索组件)
  • 繁华 李劭卓2025.3.28
  • RWEQ 模型深度讲解:结合 Python、ArcGIS 等实现土壤风蚀归因分析
  • 【CVE-2025-30208】| Vite-漏洞分析与复现
  • DQN与PPO在算法层面的核心区别
  • Binance Wallet
  • 2024年SEVC SCI1区:进化尺度适应差分进化算法ESADE,深度解析+性能实测
  • 运维面试题(十一)
  • 可以通过哪种方式实现安卓应用生成下载链接
  • 音视频 四 看书的笔记 MediaPlayerService
  • 国家统计局答澎湃:我国投资的潜力依然巨大,支撑投资增长的有利因素仍然比较多
  • “80后”北大硕士罗婕履新甘肃宁县县委常委、组织部部长
  • 玉林一河段出现十年最大洪水,一村民被冲走遇难
  • 三方合作会否受政局变化影响?“中日韩+”智库合作论坛在沪举行
  • 专利申请全球领先!去年我国卫星导航与位置服务产值超5700亿元
  • 用贝多芬八首钢琴三重奏纪念风雨并肩20年