zoukankan      html  css  js  c++  java
  • springcloud-04-自定义ribbon的配置方式

    在dubbo项目中, zookeeper即注册中心帮我们实现了调度和负载均衡的能力, 这种方式被称为服务器端的负载均衡, springcloud中, 使用ribben实现的客户端负载均衡

    什么是ribbon? 

    Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端侧负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。

    eureka使用ribbon的大致架构

    Ribbon工作时分为两步:第一步先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询round robin、随机Random、根据响应时间加权等。

    通过代码实现: 

    将刚才的cosumer-movie改造成ribbon的项目

    添加一个注解类, 需要放置在mainClass扫描不到的包下, 或者在mainClass中通过@COmponentScan进行过滤

    这儿使用的是注解过滤, 所以首先需要一个注解: 

    package com.wenbronk.cosumer.ribben.annotation;
    
    /**
     * 自定义注解, 排除不想被扫描到的内容
     * Created by wenbronk on 2017/5/18.
     */
    public @interface ExcudeAnnotation {
    }

    然后是一个ribbon的注解声明类: 

    package com.wenbronk.cosumer.ribben.config;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * 默认规则为轮询, 这个为随机规则
     * 该类必须放置在扫描不到的包下, 或者添加排除, 虽然他必须有注解
     * Created by wenbronk on 2017/5/18.
     */
    @Configuration
    @ExcudeAnnotation
    public class MyRibbonConfig {
    
        @Bean
        public IRule ribbonRule() {
            return new RandomRule();
        }
    
    }

    在mainClass中进行过滤

    package com.wenbronk.cosumer.ribben;
    
    import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation;
    import com.wenbronk.cosumer.ribben.config.MyRibbonConfig;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * 通过RIbbonClient自定义ribbon客户端
     * Created by root on 2017/5/18.
     */
    @SpringBootApplication
    @EnableEurekaClient
    // 使用此规则不可放在 可扫描的路径下, 如果非要放置, 需要加自定义注解
    @RibbonClient(name = "microserver-provider-user", configuration = MyRibbonConfig.class)
    @ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcudeAnnotation.class})})
    public class MovieRibbenApplication {
    
        /**
         * 使用LoadBalanced开启客户端负载均衡的功能
         * @return
         */
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MovieRibbenApplication.class, args);
        }
    
    }

    验证: 

    通过配置端口, 将user服务启动4个实例, 并注册为2个服务, 在movie-ribbon的controller中加入如下代码

    package com.wenbronk.cosumer.ribben.controller;
    
    import com.wenbronk.cosumer.ribben.entity.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by root on 2017/5/18.
     */
    @RestController
    public class MovieRibbenController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Autowired
        private LoadBalancerClient loadBalancerClient;
    
        @RequestMapping("/movie/{id}")
        public User findById(@PathVariable Long id) {
            return restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
        }
    
        @GetMapping("/test")
        public void test() {
            ServiceInstance instance = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER");
            System.out.println("111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort());
    //        System.out.println(instance.toString());
    
            ServiceInstance instance1 = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER-1");
            System.out.println("222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort());
    //        System.out.println(instance1);
    //        System.out.println(instance == instance1);
        }
    }

    通过浏览器重复的发送请求, 在控制台可看到只有provide-user 使用了我们自定义的规则, user-1 仍然使用的ribbon的默认规则轮询

     通过配置文件的方式, 自定义ribbonclient:

    从版本1.2.0开始,Spring Cloud Netflix现在支持使用属性与Ribbon文档兼容来自定义Ribbon客户端

     配置的优先级: 配置文件 >  java代码 > springcloud default

    配置文件配置, 只需要在yml'中添加如下内容

    users:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
    NFLoadBalancerRuleClassName 是规则, 除了此规则 springcloud还有
    每个规则可添加的类也有很多 

    mainClass.java 

    package com.wenbronk.cosumer.ribbon.yml;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by wenbronk on 2017/5/20.
     */
    @SpringBootApplication
    @EnableEurekaClient
    public class MoveiRibbonYmlApplicatoin {
    
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MoveiRibbonYmlApplicatoin.class, args);
        }
    }

    MovieRibbonController

    package com.wenbronk.cosumer.ribbon.yml.controller;
    
    import com.wenbronk.cosumer.ribbon.yml.entity.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by root on 2017/5/18.
     */
    @RestController
    public class MovieRibbenController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Autowired
        private LoadBalancerClient loadBalancerClient;
    
        @RequestMapping("/movie/{id}")
        public User findById(@PathVariable Long id) {
            return restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
        }
    
        @GetMapping("/test")
        public void test() {
            ServiceInstance instance = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER");
            System.out.println("111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort());
    //        System.out.println(instance.toString());
    
            ServiceInstance instance1 = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER-1");
            System.out.println("222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort());
    //        System.out.println(instance1);
    //        System.out.println(instance == instance1);
        }
    }
    

      

  • 相关阅读:
    【Linux】【Shell】【Basic】文件查找locate,find
    【Linux】【Shell】【text】Vim
    【Linux】【Shell】【text】文本处理工具
    【Linux】【Shell】【text】grep
    【Linux】【Basis】用户、组和权限管理
    什么是高并发;超发的解决思路(悲观锁与乐观锁);高并发与多线程的关系--持续更新(十四)
    线程池的应用(十三)
    线程池基本概念(十二)
    ThreadLocal(十一)
    tomcat的单例多线程代码示例(十)
  • 原文地址:https://www.cnblogs.com/wenbronk/p/6881643.html
Copyright © 2011-2022 走看看