Ribbon负载均衡

举报
别团等shy哥发育 发表于 2023/01/13 19:04:12 2023/01/13
【摘要】 @[toc] 1、Ribbon基础知识  Ribbon是Netflix客户端的负载均衡器,可对HTTP和TCP客户端的行为进行控制。为Ribbon配置服务器提供者地址后,Ribbon就可以基于某种负载均衡算法自动帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,也可以为Ribbon实现自定义的负载均衡算法。关于详细的负载均衡算法,请看这篇文章:htt...

@[toc]

1、Ribbon基础知识

  Ribbon是Netflix客户端的负载均衡器,可对HTTP和TCP客户端的行为进行控制。为Ribbon配置服务器提供者地址后,Ribbon就可以基于某种负载均衡算法自动帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,也可以为Ribbon实现自定义的负载均衡算法。关于详细的负载均衡算法,请看这篇文章:
https://blog.csdn.net/qq_43753724/article/details/119836860?spm=1001.2014.3001.5501
  要将Ribbon包含在项目中,请添加如下依赖:

<!--引入ribbon依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

  在Ribbon中有以下几个重要概念:

  • Rule:该组件主要决定从候选服务器中返回哪个服务器地址进行远程调用的操作。
  • Ping:在后台运行的组件,用来确认那些服务器是存货可用的。
  • ServerList:当前可以用作LB的服务器列表,该列表可以是静态的,也可是动态的。如果是动态列表(例如从Eureka服务器获取),就会有一个后台线程按照时间间隔刷新列表。

  Ribbon提供了以下几种Rule:

  • RoundRobinRule:最简单的规则,会在ServerList中依次轮询调用。
  • RandomRule:随机。
  • AvailabilityFilteringRule:在这种规则下Ribbon集成了Hystrix的功能,默认情况下调用某个远程方法失败3次后断路器的开关会被打开,而之后的请求中Ribbon会跳过这个服务器地址,直到30秒之后断路器关闭后才会重新加如调用列表。
  • WeightedResponseTimeRule:将响应时间作为权重的负载规则,某个服务器的响应时间越长,它的权重就越低。具体选择服务器时,结合权重进行随机选择。
  • RetryRule:按照RoundRobinRule(轮询)策略获取服务,如果获取服务失败,就在指定时间内重试,获取可用的服务。
  • BestAvailableRule:先过滤掉由于多次访问故障而处于段力气跳闸状态的服务,然后选择一个并发量最小的服务。
  • ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择服务器。

2、Ribbon服务调用

2.1 项目中引入依赖

<!--引入ribbon依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

说明:
1.如果使用的是eureka client 和 consul client,无须引入依赖,因为在eureka,consul中默认集成了ribbon组件
2.如果使用的client中没有ribbon依赖需要显式引入上述依赖

2.2 查看consul client中依赖的ribbon

在这里插入图片描述

2.3 启动consul服务注册中心

在这里插入图片描述

2.4 将订单服务进行注册

订单服务配置文件:
在这里插入图片描述

  这里注册两个订单服务(模仿订单服务集群),一个9990端口,一个9999端口
  使用**@Value**注解将端口号注入到port变量里面,就可以在别的服务调用的时候在页面上打印出提供服务的服务器节点的端口,方便观察负载均衡的结果。
在这里插入图片描述
在这里插入图片描述
访问8500端口即可查看服务注册中心中所注册的订单服务ORDERS
在这里插入图片描述

2.5 将RestTemplate交给Spring工厂去管理

这样我们就可以在需要使用的地方直接注入了。
BeansConfig.java

package com.baizhi.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration  //代表这是一个SpringBoot配置类  spring.xml  工厂  创建对象 bean id class=""
public class BeansConfig {

    //工厂中创建RestTemplate
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

2.6 使用RestTemplate+ribbon进行服务调用

2.6.1 使用discovery client形式调用

 @Autowired      //服务注册与发现的客户端对象
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("user")
    public String invokeDemo(){
         log.info("user demo...");

        //2、使用Ribbon+RestTemplate实现负载均衡调用 1.DiscoveryClient 2.LoadBalanceClient 3.@LoadBalance
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ORDERS");
        serviceInstances.forEach(serviceInstance -> {
            log.info("服务主机:{} 服务端口:{} 服务地址:{}",serviceInstance.getHost(),serviceInstance.getPort(),serviceInstance.getUri());
       });
       String result = new RestTemplate().getForObject(serviceInstances.get(0).getUri() + "/order", String.class);
        return "OK"+result;
    }

在用户服务中调用订单服务:http://localhost:8888/user
在这里插入图片描述
由于我们使用了(serviceInstances.get(0).getUri(),所以一致使用的是订单服务列表中的第一台节点,即9990端口的节点。可以看到,这里并没有自动帮我们做负载均衡,需要我们自己去做负载均衡的算法。

2.6.2 使用LoadBalancerClient形式调用

@RestController
@Slf4j
public class UserController {

    @Autowired      //服务注册与发现的客户端对象
    private DiscoveryClient discoveryClient;

    @Autowired  //负载均衡客户端对象
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("user")
    public String invokeDemo(){
         log.info("user demo...");
        //3、使用LoadBalancerClient进行服务调用
        ServiceInstance serviceInstance = loadBalancerClient.choose("ORDERS");  //默认轮询
        log.info("服务地址:{} 服务主机:{} 服务端口:{}",serviceInstance.getUri(),serviceInstance.getHost(),serviceInstance.getPort());
        String result = restTemplate.getForObject(serviceInstance.getUri() + "/order", String.class);


        return "OK"+result;
    }
}

这种方式的负载均衡算法默认使用的是轮询方式。即第一次调用9990端口的节点,第二次就调用9999端口的节点,以此类推。
在这里插入图片描述
在这里插入图片描述

2.6.3 使用 @LoadBalanced注解

//工厂中创建RestTemplate
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
@RestController
@Slf4j
public class UserController {

    @Autowired      //服务注册与发现的客户端对象
    private DiscoveryClient discoveryClient;

    @Autowired  //负载均衡客户端对象
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("user")
    public String invokeDemo(){
         log.info("user demo...");
        //4、使用@LoadBalance注解  作用:可以让对象具有ribbon负载均衡特性
     String result = restTemplate.getForObject("http://ORDERS/order", String.class);
        return "OK"+result;
    }
}

默认还是轮询的负载均衡算法,但是由于我们在配置文件中添加了

#修改用户服务调用订单服务默认负载均衡策略不再使用轮询 使用随机策略
ORDERS.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

所以,现在使用的负载均衡算法是随机法

2.7 修改服务的默认负载均衡策略

格式:

id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

下图中的ORDERS为服务的唯一标识。
在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。