• Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon


    Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon

    目前主流的负载均衡方案有两种,一种是集中式均衡负载,在消费者与服务提供者之间使用独立的代理方式进行负载,比如F5、Nginx等。另一种则是客户端自己做负载均衡,根据自己的请求做负载,Ribbon就属于客户端自己做负载。

    一、引入Ribbon依赖

    <dependency>
    	<groupId>org.springframework.cloudgroupId>
    	<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    二、在消费方增加@LoadBalanced负载均衡

    其实在上一节中我们已经增加了@LoadBalanced注解了。

    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaClientConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaClientConsumerApplication.class, args);
        }
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、服务提供方提供多台机器

    因为我把服务部署到了一台远程的机器上,而机器上的8000端口被别的应用占用了,因此把eurekaClient项目的端口改成了8008。部署eureka到ubuntu22.04的步骤请参考ubuntu22.04开机自启动Eureka服务。我这里开放给大家使用eureka的外网注册地址:www.huerpu.cc:1678 ,和大家交流学习。

    我们把eurekaClient项目的接口修改一下,加上自己的Server信息from server:eurekaServer:8008

    package cc.huerpu.eurekaserver.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class UserController {
    
        @RequestMapping("/getUserById")
        public String getUserById(){
            return "{id:1,name:jason,age:23} from server:eurekaServer:8008";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    复制eurekaClient项目,重命名为eurekaClientSecond,并把端口改成8009,因此现在我们有8008和8009两台服务提供者了。

    eurekaClientSecond的接口调用打印信息改成from server:eurekaServer:8009

    package cc.huerpu.eurekaserver.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class UserController {
    
        @RequestMapping("/getUserById")
        public String getUserById(){
            return "{id:1,name:jason,age:23} from server:eurekaServer:8009";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为了方便查看,在服务消费方增加一个打印语句System.out.println(res)

    @RequestMapping("/consumerEurekaClient")
    public String consumerEurekaClient(){
        String res = restTemplate.getForObject("http://eurekaClient/getUserById",String.class);
        System.out.println(res);
        return "consumerEurekaClient:" + res;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动项目eurekaClienteurekaClientSecondeurekaClientConsumer,查看eureka是否注册上这几个服务。

    image-20230908121354914

    可以看到服务注册上来了。

    四、服务调用负载验证

    调用http://eurekaclientconsumer:8001/consumerEurekaClient,查看是否有交替调用8008和8009两个,因为默认为轮询,也就是RoundRobinRule

    image-20230908145032190

    五、切换负载均衡策略

    5.1 Ribbon均衡策略

    Spring Cloud Ribbon提供了一个 IRule 接口,该接口主要用来定义负载均衡策略,它有 7 个默认实现类,每一个实现类都是一种负载均衡策略。

    实现类负载均衡策略
    RoundRobinRule按照线性轮询策略,即按照一定的顺序依次选取服务实例
    RandomRule随机选取一个服务实例
    RetryRule按照 RoundRobinRule(轮询)的策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试(重试时获取服务的策略还是 RoundRobinRule 中定义的策略),如果超过指定时间依然没获取到服务实例则返回 null 。
    WeightedResponseTimeRuleWeightedResponseTimeRule 是 RoundRobinRule 的一个子类,它对 RoundRobinRule 的功能进行了扩展。 根据平均响应时间,来计算所有服务实例的权重,响应时间越短的服务实例权重越高,被选中的概率越大。刚启动时,如果统计信息不足,则使用线性轮询策略,等信息足够时,再切换到 WeightedResponseTimeRule。
    BestAvailableRule继承自 ClientConfigEnabledRoundRobinRule。先过滤点故障或失效的服务实例,然后再选择并发量最小的服务实例。
    AvailabilityFilteringRule先过滤掉故障或失效的服务实例,然后再选择并发量较小的服务实例。
    ZoneAvoidanceRule默认的负载均衡策略,综合判断服务所在区域(zone)的性能和服务(server)的可用性,来选择服务实例。在没有区域的环境下,该策略与轮询(RandomRule)策略类似。
    5.2 设置全局生效

    设置负载均衡策略为随机,只需在启动类EurekaClientConsumerApplication上注入一个IRule的bean。

    package cc.huerpu.eurekaserver;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    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.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaClientConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaClientConsumerApplication.class, args);
        }
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        @Bean
        public IRule rule(){
            return new RandomRule();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    重启项目eurekaClientConsumer,调用http://eurekaclientconsumer:8001/consumerEurekaClient,可以看到是随机调用的。

    image-20230908150231419

    5.3 针对特定服务生效

    创建一个并注入一个RibbonConfiguration类。

    package cc.huerpu.eurekaserver.configuration;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RibbonConfiguration {
        @Bean
        public IRule ribbonRule() {
            // 负载均衡规则,改为随机
            return new RandomRule();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建一个空类TestConfiguration ,使用注解@RibbonClient,name属性指定要去调用的服务名称,由spring.pplication.name指定的那个名称。

    package cc.huerpu.eurekaserver.configuration;
    
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @RibbonClient(name = "eurekaClient", configuration = RibbonConfiguration.class)
    public class TestConfiguration {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    重启项目eurekaClientConsumer,调用http://eurekaclientconsumer:8001/consumerEurekaClient,可以看到是也是随机调用的。

    5.4 配置文件方式配置

    更推荐的一种方式是使用配置文件进行设置。

    eurekaClient:   #远程服务名称,我们这里是eurekaClient,根据自己的进行调整
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    
    • 1
    • 2
    • 3

    如果你只想看到负载均衡调用的效果,我们来写一个接口看一下吧,这样更直观一些。

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    
    @RequestMapping("/eurekaClientConsumerChooseInstance")
    public String eurekaClientConsumerChooseInstance() {
        ServiceInstance serviceInstance = loadBalancerClient.choose("eurekaClient");
        String server = serviceInstance.getServiceId()+":"
                +serviceInstance.getHost()+":"
                +serviceInstance.getPort();
        System.out.println(server);
        return server;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    Jetsonnano B01 笔记7:Mediapipe与人脸手势识别
    阿里云服务器(Ubuntu)配置nextcloud个人网盘
    git stash 操作
    oracle 与mysql兼容日期(格式:YYYY年MM月DD日)
    谷粒学院16万字笔记+1600张配图(四)——前端技术
    MySQL定时删除XX天数据
    BM23 二叉树的前序遍历
    VUE3-博客全栈 08-前端
    el-input输入框涉及到scope的校验问题
    Java版图形界面计算器
  • 原文地址:https://blog.csdn.net/JingLisen/article/details/132761022