目录
比较熔断和降级
熔断:一般是某个服务挂掉引起的。被动降级。(生产者)
降级:一般从整体微服务负荷考虑,主动降级。(消费者)
什么是Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错开源库——断路器。有如下三个作用
- 服务降级
- 服务熔断
- 接近实时的监控
熔断的3种状态
如何理解开启,关闭,半开闭呢?
开启/关闭:满足一定阈值(默认10s超过20个请求)、失败率到达一定程度(默认10s超过50%失败),所有请求都不会被转发。
半开闭:当熔断器被触发后,隔一段时间(默认5s)会进入半开闭状态。会逐个让服务进行调用尝试,服务调用正确率到达一定值才可以让熔断器关闭。未达到一定程度前都处于半开闭状态
Hystrix工作原理
1.每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中
2.执行execute()同步或异步方法
3.判断熔断器circuit-breaker是否打开,打开则跳到步骤8;进行降级策略跳到步骤5
.....
熔断的规则
sleepWindowInMillseconds:服务熔断后恢复到半开状态的时间窗口,以毫秒为单位
requestVolumeThreshold:熔断状态下尝试进入半打开状态的这个时间里允许使用正常逻辑处理的并发请求数
errorTHresholdPercentage:服务进入熔断状态的错误比例
服务降级(consumer)
引Jar包——yml文件中让feign开启hystrix——newFallbackFactory子类——把new的类使用@Component注解注入到bean——Feign接口调用时指定参数fallbackFactory=自定义类名.class
所谓服务降级就好比双十一时,某宝的访问量和交易量太大了,严重消耗服务器资源和性能。此时,我们开启降级机制,即让客户暂时无法正常使用浏览商品和交易商品外的其他功能。注意,此时功能是可以正常使用的,只是消费者暂时访问不到了。用户的请求仍然会访问到服务器,服务器返回自定义的降级信息,不进行相应业务处理。这样,由于其他模块没有压力,不占用过多资源,服务器的整体性能和效率全都供给访问和交易这两个模块或者说服务。保证核心模块的高可用支持。
注意:服务降级应该是消费者的事情,消费者配置接受的服务
具体实现,先导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
然后我们在api微服务中新增一个service实现类。这里为了演示方便,我只对DeptServiceImpl中一个方法进行了重写
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>" + id + ", 没有对应的信息,客户端提供了降级的信息,这个现在已经被关闭~")
.setDb_source("没有数据~");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public Boolean addDept(Dept dept) {
return null;
}
};
}
}
在接口中增加Feign注解的fallbackFacotry参数
通过Feign组件进行远程调用和负载均衡,需要在Feign微服务的配置文件中开启服务降级的支持
先启动注册中心,再启动提供者,再启动Feign服务者。正常情况下,请求数据返回信息
当我把提供者停掉之后,前台不会报错,而是返回我们自定义的降级信息。业务场景为,当我向某宝访问某一模块的某一业务时,服务器不会暴露给用户此服务到底是停止了,还是负载了。用户看到的界面只是降级信息处理,此时请求依然会打到服务器,但返回给用户降级信息就停止了~
服务熔断(provider)
引Jar包——定义方法使用@HystrixCommand注解,传入fallbackMethod参数对应的降级方法——启动类添加@EnableCircuitBreaker注解支持
熔断机制是对应雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或响应时间过长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。熔断之后后续请求不再转到服务器上。当检测到该节点微服务调用响应正常后恢复调用链路。
在springcloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值,默认是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand
熔断三个状态:关闭(没问题)、开启(服务出现问题)、半开(服务恢复后并不是直接关闭熔断,而是进入半开启)
具体实现分三步,首先我们在服务提供者中导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
然后在Controller中正常写一个方法,再写一个这个方法对应的熔断方法。在正常方法上加上注解后,正常方法失效走熔断方法
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private DiscoveryClient client;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("id=>" + id + ", 不存在该用户,或者信息无法找到~");
}
return dept;
}
//备选方案
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
.setDb_source("no this database in MySQL");
}
}
在启动类中添加对熔断的注解支持
当消费者调用生产者时,如果请求的数据不存在,例如10这个id,页面会显示熔断方法的内容,而不会报错
看到这你是不是想说感觉和异常没啥区别啊,注意如果你在正常的方法中写的是异常处理,会返回给用户的是这样的页面
Hystrix的Dashboard流监控
使用Hystrix的Dashboard监控客户端首先得保证提供者引入了依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后我们新建一个客户端springcloud-consumer-hystrix-dashboard,依赖如下
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.lt</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
在配置文件中配置端口
新建启动类,加上启动Dashboard的注解
package com.lt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class,args);
}
}
启动这个项目,输入网址你就可以看见野猪王的页面了http://localhost:9001/hystrix
你想监控哪个服务提供者就需要在哪个提供者的启动类中做配置
我们在8001提供者的启动类中增加如下方法,这个方法是固定的,记得在类上开启熔断器的支持,
注意,提供者必须之前在配置文件中配置了对Hystrix的支持。如果根本没有启动Hystrix功能的服务,是无法通过监控看到其信息的。
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
我们依次启动eureka,8001和新建的9001项目,在野猪王的页面下输入配置参数
然后我们先启动9001项目,再启动8001项目,当8001进行增删改查时,9001的页面中会显示监控参数