Hystrix是一个用于处理分布式系统的延迟和容错的开源库,能保证在一个依赖出问题的情况下不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
- 服务降级fallback
服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示- 程序运行异常
- 超时
- 服务熔断触发服务降级
- 线程池、信号量打满也会导致服务降级
- 服务熔断break
达到最大服务访问后,直接拒绝访问,然后调用服务降级的方法并返回友好提示 - 服务限流flowlimit
秒杀高并发等操作,严禁一窝蜂的过来拥挤
服务降级
一般是放在客户端,这里先说服务端8001端口
首先是添加pom依赖,引入hystrix
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
主启动类加上注解
@EnableHystrix
或者
@EnableCircuitBreaker
对于要降级的service实现加上注解
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandler",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
其中paymentInfoTimeoutHandler是服务降级后调用的方法名,方法需要自己写(注意,这个方法的返回类型、参数类型都要和要保护的方法保持一致),一般就是返回一个错误页面,value是最大的等待时间,由name知单位是ms,例子中是超过3s即跳转paymentInfoTimeoutHandler方法。
下面说80端口的使用。
首先添加yml配置
#开启Hystrix支持
feign:
hystrix:
enabled: true
主启动类加注解
@EnableHystrix
然后可以直接在controller层的方法中加类似注解
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandler",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
即可实现客户访问端自身的保护。
或者直接加一个全局异常方法,写在controller中,然后controller添加全局注解,
@DefaultProperties(defaultFallback = "paymentGlobalFallback")
其中paymentGlobalFallback为自定义的方法。需要时,在方法头添加注解@HystrixCommand,即可实现保护。
再或者,在客户端的service上使用注解
@FeignClient(value = "cloud-payment-hystrix-service",fallback = PaymentFallback.class)
然后定义PaymentFallback类,在类中重写,当service中的方法出现超时、程序异常、宕机则会服务降级实现PaymentFallback里面重写的方法。
注意,这里一定要在yml中配置好
#开启Hystrix支持
feign:
hystrix:
enabled: true
服务熔断
大量访问后会直接挂,然后尝试启动,如果访问量变小就会恢复服务。
在服务端8001端口service层添加
@HystrixCommand(fallbackMethod = "paymentCircuitBreakFallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),//失败率达到多少后跳闸
})
@Override
public String paymentCircuitBreaker(Integer id) {
if (id<0){
throw new RuntimeException("****id不能为负");
}
String simpleUUID = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+simpleUUID;
}
@Override
public String paymentCircuitBreakFallback(Integer id) {
return "id不能为负,请重试--------id="+id;
}
@HystrixCommand注解中的"paymentCircuitBreakFallback"是自己写的方法,它返回错误页面的信息。@HystrixProperty注解中涉及到断路器的几个重要参数是否开启断路器、快照时间窗、请求总数阈值、错误百分比阈值。
- 是否开启断路器:true即为开启
- 快照时间窗:默认是10秒,是断路器统计的时间范围
- 请求总数阈值:默认是20,在快照时间窗给定的时间内必须满足请求总数阈值才有资格熔断,否则断路器不会打开
- 错误百分比阈值:当请求总数超过请求总数阈值,且发生超时异常的百分比超过了错误百分比阈值,那么这时断路器就会打开。
上述示例中,参数id>0会输出流水号之类;参数id<0会报异常。
然后8001端口的Controller层天添加服务熔断的GetMapping
//----服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
String result = paymentService.paymentCircuitBreaker(id);
log.info("****result:"+result);
return result;
}
多次输入错误的信息(例如id多次输入负值)会导致服务熔断,熔断后即使输入正确的信息也会报错,但是一段时间后输入正确的信息又会可用,这就是服务熔断的作用。
HystrixDash的使用
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.meng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>
<dependencies>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--devtool-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
yml
server:
port: 9001
主启动类
package com.meng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
/**
* @author Administrator
*/
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class,args);
}
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
然后浏览器访问http://localhost:9001/hystrix即可,访问需要监控的8001端口http://localhost:8001/hystrix.stream
注意:这里被监控的8001端口一定要加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>