zoukankan      html  css  js  c++  java
  • Spring Cloud LoadBalancer原理讲解及自定义负载均衡器

    Spring Cloud LoadBalancer原理

    LoadBalancerClient作为负载均衡客户端,用于进行负载均衡逻辑,从服务列表中选择出一个服务地址进行调用,其内部方法为下图显示:

    (图1-1)

    在LoadBalancerClient种存在两个execute()方法,均是用来执行请求的,reconstructURI()是用来重构URL。对于LoadBalancerClient在Spring Cloud LoadBalancer中实现类则是BlockingLoadBalancerClient。BlockingLoadBalancerClient存在两个choose()方法,其实现的是图1-1中的ServiceInstanceChooser接口种的两个choose()方法(图1-2):

    (图1-2)

    在上述图片中通过通过工厂类LoadBalancerClientFactory获取具体的负载均衡器实例,后面的loadBalancer.choose(request)调用(图1-3)接口choose()方法实现根据负载均衡算法选择下一个服务器完成负载均衡。

     (图1-3)

    图1-3可以看出ReactorLiadBalancer接口ReactorLoadBalancer接口继承,ReactorLoadBalancer接口后续又被ReactorServiceInstanceLoadBalancer继承且其实现了两个方法,分别是:RandomLoadBalancer(随机负载均衡器)和RoundRobinLoadBalancer(轮询负载均衡器)。

     (图1-4)

     LoadBalancer自定义负载均衡器

     根据图1-4类图显示,我们只需要在自定义配置轮询方法时重定义ReactorServiceInstanceLoadBalancer接口即可,如下例子:

    @Configuration
    public class MyLoadBalancerConfig {
        @Bean
        public ReactorServiceInstanceLoadBalancer reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
            String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            //返回随机轮询负载均衡方式
            return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
        }
    }

    但是如果我们要自定义轮询算法该如何做呢?根据上面可以知道LoadBalancerClientFactory是创建客户机、负载均衡器和客户机配置实例的工厂。它根据客户端名称创建一个Spring ApplicationContext,并从中提取所需的bean(官方解释)。因此我们进入到LoadBalancerClientFactory类中:

    (图1-5)

    我们需要去实现它的子接口ReactorServiceInstanceLoadBalancer,因为去获取负载均衡器实例的时候,是通过去容器中查找ReactorServiceInstanceLoadBalancer类型的bean来实现的,参照RandomLoadBalancer我们进行仿写

    public class CustomRandomLoadBalancerClient implements ReactorServiceInstanceLoadBalancer {
     
        // 服务列表
        private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
     
        public CustomRandomLoadBalancerClient(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider) {
            this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        }
     
        @Override
        public Mono<Response<ServiceInstance>> choose(Request request) {
            ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();
            return supplier.get().next().map(this::getInstanceResponse);
        }
     
        /**
         * 使用随机数获取服务
         * @param instances
         * @return
         */
        private Response<ServiceInstance> getInstanceResponse(
                List<ServiceInstance> instances) {
            System.out.println("进来了");
            if (instances.isEmpty()) {
                return new EmptyResponse();
            }
     
            System.out.println("进行随机选取服务");
            // 随机算法
            int size = instances.size();
            Random random = new Random();
            ServiceInstance instance = instances.get(random.nextInt(size));
     
            return new DefaultResponse(instance);
        }
    }

    自定义配置类:

    @Configuration
    public class MyLoadBalancerConfig {
     
        // 参数 serviceInstanceListSupplierProvider 会自动注入
        @Bean
        public ReactorServiceInstanceLoadBalancer customLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider) {
            return new CustomRandomLoadBalancerClient(serviceInstanceListSupplierProvider);
        }
    }

    在项目启动类上添加@LoadBalancerClient注解:name值一定要使用服务端配置的服务名(spring.application.name),通过configuration指定自定义的配置

    @SpringBootApplication
    @LoadBalancerClient(name = "myServer", configuration = MyLoadBalancerConfig.class)
    public class BlockClientApplication {
     
        public static void main(String[] args) {
            SpringApplication.run(BlockClientApplication.class, args);
        }
    }

    以上内容参考借鉴总结得出,如有其他疑问可去一下地址查看详情:

    https://blog.csdn.net/weixin_50518271/article/details/111449560

    https://blog.csdn.net/qq_31142237/article/details/90486836

  • 相关阅读:
    20100320 ~ 20100420 小结与本月计划
    datamining的思考
    谈谈网络蜘蛛 爬开心网001的一些体会
    将 ASP.NET MVC3 Razor 项目部署到虚拟主机中
    Eclipse代码中中文字显示很小的解决办法
    U8800一键ROOT删除定制软件 安装新版Docment to go
    Android(安卓) U8800 长按 搜索键、返回键 锁屏或解锁的设置方法
    JDK5.0新特性系列3.枚举类型
    JDK5.0新特性系列1.自动装箱和拆箱
    网游运营基本概念及专业术语
  • 原文地址:https://www.cnblogs.com/linchenguang/p/15656603.html
Copyright © 2011-2022 走看看