zoukankan      html  css  js  c++  java
  • spring-cloud-gateway(三)自定义lb实现

    官方的静态lb已经满足大部分场景

    缺点是全静态,动态扩展能力不强

    动态扩展有两个方向

    方式一 是聚焦于spring-cloud-gateway本身,实现一些自定义的方法
    方式二 是依赖spring-cloud的生态,consul/nacos注册中心,或config配置中心,bus事件队列动态更新配置等

    做es的网关依赖spring-cloud,太重,方案放弃了

    个人一开始以为没有静态lb的支持,所以直接就看方式一,所实际这个需求,静态基本就满足,但也不算完全是白折腾,至少更熟悉了spring-cloud-gateway的代码和机制

    server:
      port: 9208
    spring:
      cloud:
        gateway:
          enabled: true
        discovery:
          client:
            simple:
              instances:
                es3[0]:
                  uri: http://127.0.0.1:19200
                es3[1]:
                  uri: http://127.0.0.1:19201
                es3[2]:
                  uri: http://127.0.0.1:19202
              order: 1
    

    spring-cloud-gateway 原生本地代理,配置resource即可

    纯静态有两个缺点
    1 无法动态添加或删除节点,如instances下 添加es[3] ,删除可以自动检测屏蔽,添加就不好做了
    2 即使无法动态添加,手动更改配置,再重启节点也满足要求


    自定义方式一

    实现ServiceInstanceListSupplier

    public class CustomServiceInstanceListSupplier  implements ServiceInstanceListSupplier {
    
        public CustomServiceInstanceListSupplier() {
        }
        private String aaaa;
    
        @Override
        public String getServiceId() {
            return "es2";
        }
    
        @Override
        public Flux<List<ServiceInstance>> get() {
            List<ServiceInstance> sis=new ArrayList<>();
            sis.add(0, new DefaultServiceInstance("instanceId-4","es2","127.0.0.1",9204,false));
            sis.add(1, new DefaultServiceInstance("instanceId-5","es2","127.0.0.1",9205,false));
            System.out.println("get()");
            return Flux.defer(() -> {
                return Flux.just(sis);
            });
        }
    
        @Override
        public Flux<List<ServiceInstance>> get(Request request) {
            return get();
        }
    }
    ---
    	@Bean
    	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
    			ConfigurableApplicationContext context) {
    		return ServiceInstanceListSupplier.builder()
    				.withBase(new CustomServiceInstanceListSupplier())
    //				.withHints()
    //				.withHealthChecks()
    				.build(context);
    	}
    

    自定义方式二,与方式一类似

    实现DiscoveryClient 并结合DiscoveryClientServiceInstanceListSupplier使用

    public class CustomDiscoveryClient implements DiscoveryClient {
        private List<ServiceInstance> instances;
        private String myServiceId;
        public CustomDiscoveryClient(List<ServiceInstance> instances) {
            this.myServiceId=myServiceId;
            this.instances=instances;
            loadInstancesFromRemote();
        }
        public void loadInstancesFromRemote(){
            List<ServiceInstance> serviceInstanceList2=new ArrayList<>();
            serviceInstanceList2.add(0, new DefaultServiceInstance("instanceId-0","ces2","127.0.0.1",9200,false));
            setInstances(serviceInstanceList2);
        }
    
        public String getMyServiceId() {
            return myServiceId;
        }
    
        public void setInstances(List<ServiceInstance> instances) {
            this.instances=instances;
        }
    
        @Override
        public String description() {
            return null;
        }
    
        @Override
        public List<ServiceInstance> getInstances(String serviceId) {
            return this.instances;
        }
        @Override
        public List<String> getServices() {
            return null;
        }
    
    }
    
    @Bean
    	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
    			ConfigurableApplicationContext context) {
        		CustomDiscoveryClient cdc2=new CustomDiscoveryClient(null);
    		  DiscoveryClientServiceInstanceListSupplier listSupplier=new        DiscoveryClientServiceInstanceListSupplier(cdc2,context.getEnvironment());
    		return ServiceInstanceListSupplier.builder()
    				.withBase(listSupplier)
    				.build(context);
    	}
    

    再提供一个外部的webapi,添加或删除节点,则一个基本的动态lb功能就完备了

    添加lb节点,删除lb节点,加载配置使lb变更生效

    自定义方式三


        @Bean
       ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                 LoadBalancerClientFactory loadBalancerClientFactory) {
          return new RandomLoadBalancer(loadBalancerClientFactory
                "es");
       }
    

    方式三功能最细致

    简而方式,方式一/方式二,都是注册全局的ServiceInstanceListSupplier,全局生效

    方式三,自定义返回 RandomLoadBalancer,构造函数包含ServiceInstanceListSupplier,可以在外层生成对应的ServiceInstanceListSupplier

        public RandomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
            this.serviceId = serviceId;
            this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        }    
    

    也可以完全不依赖官方的ServiceInstanceListSupplier,实现完全自定义的ReactorLoadBalancer

  • 相关阅读:
    JS高程3:面向对象的程序设计——理解对象
    JS高程3:函数表达式
    JS高程3:事件
    JS高程3:表单脚本
    InnoDB:表
    InnoDB:文件
    Springboot项目配置druid数据库连接池,并监控统计功能
    linux上修改mysql登陆密码
    上传本地文件到GitHub上
    logback.xml的使用,将日志异步保存到数据库中
  • 原文地址:https://www.cnblogs.com/zihunqingxin/p/14916185.html
Copyright © 2011-2022 走看看