学习目标
- Ribbon
- 负载均衡
- Ribbon的使用
- Ribbon的负载均衡策略
- Ribbon的原理
- Hystrix
- 服务的可用性
- Hystrix的配置
- Hystrix的工作机制
负载均衡
因为请求量特别大的情况下,必须有多台服务来进行处理,配置集群。
集群中的机器可能出现忙闲不均的情况,就需要有一套机制,实现平均分配请求量到每台机器上——负载均衡
负载均衡分类
- 硬件负载均衡 —— F5
- 软件负载均衡
服务端负载均衡 如:Nginx
客户端负载均衡 如:Ribbon
Ribbon的使用
-
引入依赖 neflix-ribbon
eureka-client依赖中已经包含此依赖
-
配置RestTemplate的方法上加@LoadBalanced 注解
配置伪集群测试负载均衡
package com.example.productservice.controller;
import com.example.productservice.entity.Product;
import com.example.productservice.service.ProductService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private Integer port;
@HystrixCommand(fallbackMethod = "findDefaultPro")
@GetMapping("product/{id}")
public ResponseEntity<Product> findProById(@PathVariable("id") Integer id){
Product product = productService.findProductById(id);
String name = product.getName()+ port;
product.setName(name);
return ResponseEntity.ok(product);
}
}
Ribbon的负载均衡策略
所有的负载均衡策略实现IRule接口,可以自定义
系统提供了几种策略
内置负载均衡规则类 | 规则描述 |
---|---|
RoundRobinRule | 简单轮询服务列表来选择服务器。 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。注意:可以通过修改配置loadbalancer…connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的…ActiveConnectionsLimit属性进行配置。 |
WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。它是Ribbon默认的负载均衡规则,继承于RoundRobinRule。 |
BestAvailableRule | 忽略哪些短路的服务器,并选择并发数较低的服务器。 |
RandomRule | 随机选择一个可用的服务器。 |
RetryRule | 重试机制的选择逻辑 |
配置方法:
-
全局配置
ribbon.NFLoadBalancerRuleClassName=策略名称
-
局部配置
服务名.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.策略名称类名
Ribbon的负载均衡主要由拦截器实现
服务的可用性
服务能一直在线提供服务的时间
导致服务不可用的情况:
- 流量激增,导致服务器等待或者宕机
- 硬件问题,如:自然灾害、人为破坏
- 软件bug,异常、死循环、死锁…
- 缓存击穿,导致数据库宕机
- 程序响应超时
解决方法:
- 限流,限制到服务器上的流量
- 服务器集群、多机房容灾、异地多活
- 增强测试
- 缓存保护机制
- 熔断机制
服务的雪崩:
服务的调用是链式的,一个服务出现长时间阻塞,就会阻塞后面调用它的服务,导致整个服务链都不可用。用一个词来形容就是牵一发而动全身。
熔断:
被调用的服务一直没有响应,直接断开连接
降级:
服务熔断后,服务由正常降级为缺省,返回兜底数据(缺省数据)
Hystrix的使用
Neflix提供的熔断器组件,当服务出现长时间等待或不可用情况,能实现熔断和降级处理
使用方法:
- 给服务引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
- 启动类加@EnableHystrix 或 @EnableCircuitBreaker
- 给被调用的方法加@HystrixCommand注解
- 在控制器类中添加方法,返回兜底数据
@HystrixCommand(fallbackMethod = "getDefaultProduct")
@GetMapping("/product/{id}")
public ResponseEntity<Product> findProductById(@PathVariable("id")Long id){
try {
int millis = new Random().nextInt(3000);
System.out.println("等待时间:" + millis);
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
//返回模拟数据
Product product = new Product(id,"测试商品" + port,99.98);
return ResponseEntity.ok(product);
}
/**
* 降级处理的方法
* @param id
* @return
*/
public ResponseEntity<Product> getDefaultProduct(@PathVariable("id")Long id){
//返回模拟数据
Product product = new Product(id,"兜底数据---商品" ,0.0);
return ResponseEntity.ok(product);
}
自定义熔断时间
在配置文件中配置
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
Hystrix的隔离机制
Hystrix为每个调用的方法配置了单独隔离的资源
隔离机制有
-
线程池隔离
为每个调用的方法单独分配线程池,每个方法的调用使用自己的线程池
优点:
- 可以控制并发量,起到削峰的作用
- 对任务实现异步处理,任务多了可以在线程池排队慢慢处理
缺点:
- 系统资源的消耗比较大
- 控制比较复杂
- 信号量隔离
为每个调用的方法设置阈值,每次调用会记录次数(信号量),信号量超过阈值后,直接放弃
缺点:
- 功能简单,超过阈值直接放弃
优点:
- 系统资源的消耗较少
- 控制比较简单
# 设置隔离策略 THREAD\SEMAPHORE
hystrix.command.default.execution.isolation.strategy=THREAD