• 使用Java代码自定义Ribbon配置


    很多场景下,需要实现不同的微服务采用不同的策略,例如修改Ribbon的负载均衡规则等。Spring Cloud允许使用Java代码自定义Ribbon的配置。

    在Spring Cloud中,Ribbon默认配置如下

    IClientConfig:Ribbon 的客户端配置,默认采用 com.netflix.client.config.DefaultClientConfigImpl 实现。
    IRule:Ribbon 的负载均衡策略,默认采用 com.netflix.loadbalancer.ZoneAvoidanceRule 实现,该策略能够在多区域环境下选择最佳区域的实例进行访问
    IPing:Ribbon 的实例检查策略,默认采用 com.netflix.loadbalancer.NoOpPing 实现,该检查策略是一个特殊的实现,实际上他并不会检查实例是否可用,而是始终返回 true ,默认认为所有服务实例都是可以使用
    ServerList<Server>:服务实例清单的维护机制,默认采用 com.netflix.loadbalancer.ConfigurationBasedServerList 实现。
    ServerListFilter<Server>:服务实例清单过滤机制,默认采用 org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter 实现,该策略能够优先过滤出与请求调用方处理同区域的服务实现
    ILoadBalancer:负载均衡器,默认采用 com.netflix.loadbalancer.ZoneAwareLoadBalancer 实现,他具备了区域感知的能力

    现使用Java代码自定义Ribbon配置,模拟mima-cloud-producer 服务采用轮询的方式访问,mima-cloud-producer2服务采用随机的方式访问。
    mima-cloud-producer 服务启动如下节点:

    http://localhost:9905/
    http://localhost:9906/

    mima-cloud-producer2 服务启动如下节点:

    http://localhost:9907/
    http://localhost:9908/

    打开浏览器,多次访问 http://192.168.1.100:8803/ribbon/get/1,运行效果如下:

    host:PC-20161120GHGR,port:9906,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9906
    host:PC-20161120GHGR,port:9908,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9908
    =============
    host:PC-20161120GHGR,port:9905,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9905
    host:PC-20161120GHGR,port:9908,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9908
    =============
    host:PC-20161120GHGR,port:9906,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9906
    host:PC-20161120GHGR,port:9908,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9908
    =============
    host:PC-20161120GHGR,port:9905,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9905
    host:PC-20161120GHGR,port:9908,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9908
    =============
    host:PC-20161120GHGR,port:9906,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9906
    host:PC-20161120GHGR,port:9907,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9907
    =============
    host:PC-20161120GHGR,port:9905,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9905
    host:PC-20161120GHGR,port:9907,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9907
    =============
    host:PC-20161120GHGR,port:9906,serviceId=mima-cloud-producer,uri=http://PC-20161120GHGR:9906
    host:PC-20161120GHGR,port:9908,serviceId=mima-cloud-producer2,uri=http://PC-20161120GHGR:9908
    =============

    从运行结果来看,可以发现mima-cloud-producer服务采用轮询的方式,mima-cloud-producer2服务采用随机的方式。

    1、创建Ribbon配置类
    1.1、ConsumerRibbonClientConfig——Ribbon配置类,采用轮询的策略

    package com.mimaxueyuan.consumer.config;
    
    import org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.DummyPing;
    import com.netflix.loadbalancer.ILoadBalancer;
    import com.netflix.loadbalancer.IPing;
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.PollingServerListUpdater;
    import com.netflix.loadbalancer.Server;
    import com.netflix.loadbalancer.ServerList;
    import com.netflix.loadbalancer.ServerListFilter;
    import com.netflix.loadbalancer.ServerListUpdater;
    import com.netflix.loadbalancer.ZoneAvoidanceRule;
    import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
    
    //自定义ribbon策略可以覆盖RibbonClientConfiguration中的默认配置。
    //RibbonClientConfiguration每个方法都可以被覆盖
    //自定义的Ribbon配置不能放在SpringApplication的同级或下级目录中会覆盖所有的Ribbon客户端配置,所有的客户端都使用了相同的配置。
    //自定义的Ribbon配置不能放在ComponentScan的目录中否则次配置会覆盖所有的Ribbon客户端配置,所有的客户端都使用了相同的配置。
    @Configuration
    public class ConsumerRibbonClientConfig {
    
        public static final int DEFAULT_CONNECT_TIMEOUT = 1000;
        public static final int DEFAULT_READ_TIMEOUT = 1000;
        
        @Bean
        public IRule ribbonRule(IClientConfig config) {
         //轮询策略 ZoneAvoidanceRule rule
    = new ZoneAvoidanceRule(); rule.initWithNiwsConfig(config); return rule; } // 检测服务是否存活 @Bean public IPing ribbonPing(IClientConfig config) { return new DummyPing(); } /* 服务列保, 覆盖此方法,必须在yml/properties文件中配置服务列表 @Bean public ServerList<Server> ribbonServerList(IClientConfig config) { ConfigurationBasedServerList serverList = new ConfigurationBasedServerList(); serverList.initWithNiwsConfig(config); return serverList; } */ //服务列表更新器 @Bean public ServerListUpdater ribbonServerListUpdater(IClientConfig config) { return new PollingServerListUpdater(config); } //负载均衡器 @Bean public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) { return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList, serverListFilter, serverListUpdater); } //此接口允许过滤配置或动态获得的具有良好特性的候选服务器列表。 @Bean public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) { ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter(); filter.initWithNiwsConfig(config); return filter; } }

    1.2、ConsumerRibbonClientConfig2——Ribbon配置类,采用随机的策略

    package com.mimaxueyuan.consumer.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    
    //自定义ribbon策略可以覆盖RibbonClientConfiguration中的默认配置。
    //RibbonClientConfiguration每个方法都可以被覆盖
    //自定义的Ribbon配置不能放在SpringApplication的同级或下级目录中会覆盖所有的Ribbon客户端配置,所有的客户端都使用了相同的配置。
    //自定义的Ribbon配置不能放在ComponentScan的目录中否则次配置会覆盖所有的Ribbon客户端配置,所有的客户端都使用了相同的配置。
    @Configuration
    public class ConsumerRibbonClientConfig2 {
        
        @Bean
        public IRule ribbonRule(IClientConfig config) {
            // 负载均衡规则,改为随机
            return new RandomRule();
        }
    }

    2、RibbonConsumerApplication——Ribbon启动类,及指定Ribbon的配置类

    package com.mimaxueyuan.consumer.robbin;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Primary;
    import org.springframework.web.client.RestTemplate;
    
    import com.mimaxueyuan.consumer.config.ConsumerRibbonClientConfig;
    import com.mimaxueyuan.consumer.config.ConsumerRibbonClientConfig2;
    
    @SpringBootApplication
    //@EnableEurekaClient
    @EnableDiscoveryClient
    //name=服务提供者的instanceName,configuration指定Ribbon的配置类
    //@RibbonClient(name="mima-cloud-producer",configuration=ConsumerRibbonClientConfig.class)
    @RibbonClients(
            //配置defaultConfiguration会报空指针异常,有知道的同学麻烦告诉下
            //defaultConfiguration=RibbonClientConfiguration.class, 
            value= {
        @RibbonClient(name="mima-cloud-producer",configuration=ConsumerRibbonClientConfig.class),
        @RibbonClient(name="mima-cloud-producer2",configuration=ConsumerRibbonClientConfig2.class)
    })
    public class RibbonConsumerApplication {
    
        @Bean
        // 需要使用负载均衡,必须与Bean一同使用
        @LoadBalanced
        public RestTemplate balanceRestTemplate() {
            return new RestTemplate();
        }
        
        //需要多个RestTemplate, 有的RestTemplate使用负载均衡,有的不使用,不使用的不增加@LoadBalanced注解
        @Primary
        @Bean
        public RestTemplate noBalanceRestTemplate() {
            return new RestTemplate();
        }
        
    
        public static void main(String[] args) {
            SpringApplication.run(RibbonConsumerApplication.class, args);
        }
    
    }

    3、RibbonConfigController——Ribbon测试类

    package com.mimaxueyuan.consumer.robbin.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class RibbonConfigController {
    
        // 注入restTemplate, 这个类已经在RibbonConsumerApplication中初始化,并且使用负载均衡
        @Autowired //默认按照类型注入,如果需要按照名字注入需要使用@Qualifier注解
        @LoadBalanced //使用带有负载均衡的RestTemplate
        private RestTemplate balanceRestTemplate;
    
        // 以下注入负载均衡客户端LoadBalancerClient是一个接口,下面只有一个RibbonLoadBalancerClient实现类
        @Autowired
        private LoadBalancerClient loadBalancerClient;
        @Autowired
        private RibbonLoadBalancerClient ribbonLoadBalancerClient;
    
        /**
         * ribbon使用
         *
         * @author Kevin
         * @Title: ribbon 
         * @param id
         * @return
         * @return: String
         */
        @GetMapping("/ribbon/get/{id}")
        public String ribbon(@PathVariable("id") String id) {
            ServiceInstance instance = loadBalancerClient.choose("mima-cloud-producer");
            System.out.println("host:" + instance.getHost() + ",port:" + instance.getPort() + ",serviceId=" + instance.getServiceId() + ",uri=" + instance.getUri());
            instance = ribbonLoadBalancerClient.choose("mima-cloud-producer2");
            System.out.println("host:" + instance.getHost() + ",port:" + instance.getPort() + ",serviceId=" + instance.getServiceId() + ",uri=" + instance.getUri());
            System.out.println("=============");
            return "ribbon's demo,please to see console output";
        }
        
    }

     

  • 相关阅读:
    java 实验五保存网页到本地
    Codeforces Round #485 (Div. 2)F. AND Graph
    算法设计分析实验三——贪心求最小生成树
    D. XOR-pyramid Codeforces Round #483 (Div. 2) dp
    C. Finite or not? Codeforces Round #483 (Div. 2)
    Educational Codeforces Round 44 F. Isomorphic Strings
    Educational Codeforces Round 44 (Rated for Div. 2)+E. Pencils and Boxes+树状数组
    BZOJ 1012 [JSOI2008]最大数maxnumber
    BZOJ 1207 [HNOI2004]打鼹鼠(简单dp)
    POJ 3067 Japan(树状数组求逆序对)
  • 原文地址:https://www.cnblogs.com/linjiqin/p/10113839.html
Copyright © 2020-2023  润新知