一. 客户端负载均衡器Ribbon
1. 什么是服务端负载均衡
之前研究nacos的时候也说过服务端负载均衡和客户端负载均衡. 其实我们常用的服务端负载均衡就是nginx
在负载均衡中维护一个可用的服务实例清单, 当客户端请求来临时, 负载均衡服务器按照某种配置好的规则(负载均衡算法), 从可用服务实例清单中, 选取其一去处理客户端请求, 这就是服务端负载均衡, 例如Nginx. 通过nginx进行负载均衡, 客户端发送请求值Nginx, nginx通过负载均衡算法, 在多个服务器之间选择一个进行访问.
2. 什么是客户端负载均衡
接下来, 我们要讲的ribbon, 就属于客户端负载均衡, 在ribbon客户端会有一个服务实例地址列表, 在发送请求前, 通过负载均衡算法, 选择一个服务实例, 然后进行访问, 这是客户端负载均衡. 即在客户端进行负载均衡算法分配.
3. 客户端负载均衡的用法
先面我们先来看看ribbon负载均衡的效果
第一步: 添加依赖
我么拷贝了一个order项目, 为其添加ribbon依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
第二步: 增加注解: @LoadBalance
这里在实例化RestTemplate的时候, 增加一个注解@LoadBalanced.
我们之前在研究zuul的时候, 好像没有配置过这个注解呀, 为什么呢?因为在zuul里调用的时候使用feign, feign里面实现了这个负载均衡.
第三步: 在order服务中调用product服务, 使用的是restTemplate方式调用
package com.lxl.www.gateway.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @Slf4j @RestController public class UserController { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @GetMapping("get/user") public String getUser() { String forObject = restTemplate.getForObject("http://product/config", String.class); System.out.println(forObject); return forObject; } }
第四步: 验证效果
启动order服务1台-里面添加了ribbon依赖配置, 端口号是8080
启动product服务3台, 端口号分别是8081, 8082, 8083
product的详情信息
请求服务
http://localhost:8080/get/order
我们看到调用了3次, 每个实例被调用1次
二. 配置ribbon负载均衡策略
我们看到了ribbon的基本用法, 知道他的一个基本的实现原理, 下面来看看ribbon的基本配置
1. ribbon默认的负载均衡策略
ribbon自带的负债均衡策略一共有6中
- RandomRule: 是随机策略
- RoundRobinRule: 轮询策略
- RetryRule: 重试策略
- ZoneAvoidanceRule: 地域内轮询策略(默认策略). 这里zone在亚马逊服务器上有,在阿里云上没有这个概念, 所以可以不考虑zone, 那么这个策略相当于轮询.
- PredicateBaseRule:
- WeightedResponseTimeRule: 权重响应策略
最后我们来看看这些策略的具体实现
2. 修改系统默认的负债均衡策略, 默认的是轮询, 我们将其修改为随机策略
其实很简单, 我们重新指定IRule规则即可, 这里设置的是随机策略.
后面在配置文件中也可已设置每一个项目的负载均衡策略. 但是如果这里和配置文件都设置了, 那么以这里的为准
3. ribbon的细粒度自定义配置
比如,现在有一个场景, 有三个服务, 一个订单, 一个产品, 一个交易
订单调用产品采用的负载均衡策略是轮询, 订单调用交易服务采用的负载均衡策略是随机
怎么办呢? 我们可以在配置文件中配置每一个服务的负载均衡策略, 我们来看看如何做呢?
有两种方案, 方案一, 写java类实现. 方案二, 通过配置实现
方案一:
第一步, 我们自定义需要配置的类, 重点: 这些类不能够被系统扫描到
所谓的不能被扫描到指的是, 不能被启动类Application扫描到, 那么就要放在其外面的子包里面.
(一旦被系统扫描到, 就变成了一个全局的配置类)
我们开一下如何配置
第二步: 这里定义了两个配置类Customerconfiguration和ProductConfiguration, 其中customer使用的是RandomRule()随机策略, 而Product使用RoundRobinRule()策略.
@Configuration public class ProductConfiguration { @Bean public IRule getRule() { return new RoundRobinRule(); } } @Configuration public class CustomerConfiguration { @Bean public IRule getRule() { return new RandomRule(); } }
然后自定义一个配置文件CustomeRibbonConfig, 并指定每个项目使用的负载均衡策略
第三步:运行项目
启动三台product, 三台customer ,一台gateway
然后访问链接
http://localhost:8080/get/product http://localhost:8080/get/customer
可以看到一个是轮询的效果, 一个是随机的效果
方案二:
重点: 我们还有一种简单的基于配置的方法. (推荐使用)
# 所有项目公用的配置策略
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
# 带有项目名称的ribbon配置,仅对某个项目生效
product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
customer:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
4. ribbon配置详解
ribbon:
ReadTimeout: 1000
ConnectTimeout: 1000
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
OkToRetryOnAllOperations: false
http:
client:
enabled: true
MaxAutoRetries的含义?
每一台服务器重试的次数, 不包含首次调用的那一次 ribbon.MaxAutoRetries=1 含义是如果调用服务失败了, 那么重试1次
MaxAutoRetriesNextServer的含义:
重试服务器的个数, 不包含首次调用的那一台实例 ribbon.MaxAutoRetriesNextServer=2 含义是是: 如果负载均衡选择了服务器1, 结果调用失败, 重试还是失败了. 那么这是可以选择重试除了这台服务器的其他服务器. 可以重试几台呢? 可以重试两台
OkToRetryOnAllOperations的含义
这里是对http方法进行重试设置, 可以设置成true或者false
如果设置为true: 则表示post,put等方法也会进行重试. 这样会导致的问题是, 重复提交. 要避免这个事情的发生, 要保证服务的幂等性
什么是服务的幂等性呢?
看一下这篇文章就明白了: https://www.cnblogs.com/QG-whz/p/10372458.html
as