一:学习目标
①什么是Ribbon,②Ribbon解决了什么问题,③负载均衡不同方案的区别,④Ribbon负载均衡策略,⑤Ribbon入门案列,⑥Ribbon点对点直连(跳过负载均衡,在测试的时候更加方便),⑦Ribbon负载均衡策略设置.
二:什么是Ribbon
(就是我们消费方进行调用服务的时候(服务是好多个),这个时候我们需要从这么多服务中挑选)选择哪个结点(怎么分散的选取对应的服务提供方呢)
我们本来有注册中心,服务提供方,服务消费方;
服务提供方将服务提供方将服务注册到注册中心后,我们的服务消费方从注册中心中拉取列表,(重点)这个时候我们的消费方就远程调用提供方(我们的Ribbon就在这个实现负载均衡)
①:Ribbon 是一个基于 HTTP 和 TCP 的 客服端 负载均衡工具,它是基于 Netflflix Ribbon 实现的。它不像 Spring Cloud 服务注册中心、配置中心、API 网关那样独立部署,但是它几乎存在于每个 Spring Cloud微服务中。包括 Feign 提供的声明式服务调用也是基于该 Ribbon 实现的。Ribbon 默认提供很多种负载均衡算法,例如轮询、随机等等。甚至包含自定义的负载均衡算法。
三:负载均衡不同方案的区别
目前业界主流的负载均衡方案可分成两类(Ribbon属于第二种): 集中式负载均衡(服务器负载均衡),即在 consumer 和 provider 之间使用独立的负载均衡设施(可以是硬 件,如 F5,也可以是软件,如 nginx),由该设施负责把访问请求通过某种策略转发至 provider;(左图) 进程内负载均衡(客户端负载均衡)Ribbon属于这种,将负载均衡逻辑集成到 consumer,consumer 从服务注册中心获知有 哪些地址可用,然后自己再从这些地址中选择出一个合适的 provider。Ribbon 属于后者,它只是一个类库,集 成于 consumer 进程,consumer 通过它来获取 provider 的地址。(右图)
|
|
四:Ribbon负载均衡策略
①轮询策略(默认)
策略对应类名: RoundRobinRule 实现原理:轮询策略表示每次都顺序取下一个 provider,比如一共有 5 个 provider,第 1 次取第 1 个,第 2 次取第 2 个,第 3 次取第 3 个,以此类推。 ②权重轮询策略策略对应类名: WeightedResponseTimeRule 实现原理: 根据每个 provider 的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低。 原理:一开始为轮询策略,并开启一个计时器,每 30 秒收集一次每个 provider 的平均响应时间,当信息足够时,给每个 provider 附上一个权重,并按权重随机选择 provider,高权越重的 provider 会被高概率选中。 ③随机策略
策略对应类名: RandomRule 实现原理:从 provider 列表中随机选择一个。 ④最少并发数策略
策略对应类名: BestAvailableRule 实现原理:选择正在请求中的并发数最小的 provider,除非这个 provider 在熔断中。 ⑤重试策略(轮询策略的增强版)
策略对应类名: RetryRule 实现原理:其实就是轮询策略的增强版,轮询策略服务不可用时不做处理,重试策略服务不可用时会重新尝试集 群中的其他节点。 ⑥可用性敏感策略
策略对应类名: AvailabilityFilteringRule 实现原理:过滤性能差的 provider 第一种:过滤掉在 Eureka 中处于一直连接失败的 provider。 第二种:过滤掉高并发(繁忙)的 provider。 ⑦区域敏感性策略
策略对应类名: ZoneAvoidanceRule 实现原理: 以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的 provider。 如果这个 ip 区域内有一个或多个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选中的权 重。 五:Ribbon入门案列 ①首先创建一个service-prover02的module ②将我们的ervice-prover的pom,以及包和类复制过来 ③将service-prover的yml复制过来,把端口改为7071 ④将Eureka-server03启动和Eureka-server启动,将service-prover与service-prover02启动 ⑤查看我们现在的服务
⑥我们修改一下我们的consumer中的impl类
将//负载均衡器 Ribbon 负载均衡器
@Autowired
private LoadBalancerClient loadBalancerClient;设置这个当做我们的连接
public order selectOrderById(Integer id) { return new order(id,"order-001","中国",319940D,selectProductListBydiscoveryClient1()); } private List<product> selectProductListBydiscoveryClient1(){ StringBuffer sb=null; //获取服务列表 这里没有了获取服务列表 //根据服务名称获取服务 ServiceInstance si=loadBalancerClient.choose("SERVICE-PRODUCT"); if (si==null) return null; sb=new StringBuffer(); sb.append("http://"+si.getHost()+":"+si.getPort()+"/product/list"); //为了测试我们的Ribbon策略,打印出来我们具体调用的是哪个生产者 System.out.println("sb.tostring:"+sb.toString()); //ResponseEntity : 封装了返回数据 ResponseEntity<List<product>> response=restTemplate.exchange( sb.toString(), HttpMethod.GET, null, new ParameterizedTypeReference<List<product>>(){} ); return response.getBody(); }
记得把启动类的负载均衡去掉:
⑦启动consumer应用
在输入
查看我们的console输出台(调用的是prover的):
再次请求一下结果(请求的是prover02):
再多次请求一下(默认采用的是轮询策略):
六:Ribbon负载均衡策略设置
①全局的:在启动类或配置类中注入负载均衡策略对象。所有服务请求均使用该策略。
我们在启动类中注入Bean,全局都是以这种方式进行远程调用(我们使用的是随机策略)
//@EnableEurekaClient //@EnableEurekaClient 注解,目前版本如果配置了Client注册中心,默认会开启该注解 @SpringBootApplication public class ServiceConsumerApplication { //这里直接注入负载均衡的策略,我们这里使用的是随机 @Bean public RandomRule randomRule(){ return new RandomRule(); } @Bean // @LoadBalanced //负载均衡注解 public RestTemplate restTemplate(){ return new RestTemplate(); } public static void main( String[] args ) { SpringApplication.run(ServiceConsumerApplication.class,args); } }
现在进行访问(这是随机访问的结果):
②局部(设置配置文件,看具体的哪个微服务用什么策略)这个是在消费者的配置文件写具体生产者的策略
修改配置文件指定服务的负载均衡策略(NFLoadBalancerRuleClassName为策略)。格式: 服务应用名.ribbon.NFLoadBalancerRuleClassName我们进行访问(这里的策略是随机的策略):
七:Ribbon点对点直连(没有从注册中心拉取,直接通过Ribbon点对点直连)
指的是我们的消费者跳过注册中心,直接去请求生产者(一般在我们的测试环境中用)
①先打开consumer中的pom文件中,将eureka-client的注销掉
②把consumer中的yml文件中的eureka也注销掉
③接下来我们把Ribbon的依赖拉进来(我们用的是Ribbon直连的)
④我们现在要直连,直连的服务是哪几个呢,需要在yml中配置一下
⑤将显示的Eureka关闭,因为默认是开启的
⑥:现在只需要启动服务提供者和服务消费者
现在我们的prover与prover02 都是报错的,因为我们没有Eureka启动,所以会报错,当我们启动consumer后,我们进行访问:
访问 关闭 Eureka 注册中心,服务提供者由于无法连接至注册中心所以会报连接异常。但是服务是可以正常可消费 的,所以目前使用的是点对点的方式来进行调用的。