概念
负载均衡
将用户的请求平摊分配到多个服务器上,从而达到系统的HA(高可用)。
常见的负载均衡有软件Nginx,LVS,硬件F5等。
服务器负载均衡
Nginx是服务器负载均衡,客户端会把所有的请求都交给nginx实现转发请求。
(例如你去医院看病,Nginx就相当于大门,医院有内科,外科,骨科等等,然后你牙齿痛,你要去看口腔科。)
集中式负载均衡:在服务的消费方和提供方使用独立的LB(Load Balance)设施(如Nginx),ba访问者的请求通过某种策略发至服务提供方
本地负载均
在调用微服务接口的时候,会在主次中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
(你来到了口腔科这里,你需要挂专家号,挂号的人肯定很多,整个口腔科里边肯定不止一个专家,专家也会排班,轮着给你们看病.)
进程内负载均衡:将LB(Load Balance)逻辑集成呢感到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon
Ribbon是一个基于http和tcp的客户端负载均衡工具,它提供了多种负载均衡算法,例如:轮询,随机等。提供了一套微服务负载均衡解决方案。
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方式通过它来获取到服务提供的地址。
快速入门
我们先了解一下restTemplate的基本使用
方法 | 说明 |
---|---|
getForObject() | 返回对象为响应体中数据转化成的对象,基本上可以理解为Json |
getForEntity() | 返回对象为ResponseEntity对象,包含了相应中的一些重要信息,比如响应头,响应状态码,响应体等。 |
案例:
@RestController
@Slf4j
public class OrderController {
// public static final String PAYMENT_URL = "http://localhost:8001";
// CLOUD-PAYMENT-SERVICE 是微服务名称
public static String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
log.info("********地址:{}******", PAYMENT_URL + "/payment/get/" + id);
return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
}
@GetMapping("/consumer/payment/getEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
ResponseEntity<CommonResult> forEntity =
restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
log.info("请求信息:》》》》》》》》》》"+forEntity.getStatusCode()+":"+forEntity.getHeaders());
if (forEntity.getStatusCode().is2xxSuccessful()){
return forEntity.getBody();
}else {
return new CommonResult<>(404,"未知错误");
}
}
}
Ribbon
<!--eureka-client eureka已经集成了ribbon,所以不用单独引入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Ribbon自带的负载均衡规则
Ribbon的核心组件IRule
负载均衡规则 | 说明 |
---|---|
RoundRobinRule | 轮询 |
RandomRule | 随机 |
RetryRule | 名词解释:重试规则。先按照轮询策略获取服务,获取失败会在指定的时间内重试,获取可用的服务 |
WeightedResponseTimeRule | 名词解释:加权响应时间规则。对轮询的扩展,响应速度越快的实力选择权重越大,越容易被选择。 |
BestAvailableRule | 名词解释:最佳可用规则。会先过滤掉由于多次访问故障处于断路跳闸状态的服务,然后选择一个并发量最小的服务。 |
AvailabilityFilteringRule | 名词解释:可用性过滤规则。先过滤故障实例,再选择并发较小的实例。 |
ZoneAvoidanceRule | 名词解释:区回避规则。默认规则,复合判断server所在区域的性能和server的可用性选择服务器。 |
Ribbon替换负载均衡规则
默认规则是轮询
案例:
注意:自定义配置类不能放在@componentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊定制化的目的(这是官方给出的警告)
目录结构:
也就是说自定义配置类得放在主启动类以外的包里面
// 替换为随机规则
/**
* ribbon规则
* 默认是轮询
*
*/
@Configuration
public class MySelfRule {
/**
* 定义随机负载均衡规则
* @return
*/
@Bean
public IRule iRule(){
return new RandomRule();
}
}
@SpringBootApplication
@EnableEurekaClient
// ribbon客户端 name是服务提供者,configuration是自定义配置类
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
@Bean
@LoadBalanced // 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
Ribbon负载均衡轮询算法
原理:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始。
假设两台服务器
List = 2 instance
第一次请求:1 % 2 = 1 list.get(1)
第二次请求: 2 % 2 = 0 list.get(0)
rest请求次数 | 服务器数量 | 服务器位置下标 |
---|---|---|
1 | 2 | 1 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 2 | 0 |
5 | 2 | 1 |