熔断和降级简单理解:
降级:代码是稳定的,但是请求次数不稳定,当服务器压力大的时候,或者某些出现了不可避免地错误,比如网络断开 之类的。而客户端(consumer)是并不想看到一些代码报错 || 服务器超时,用户也不并不想等待,这时候就需要降级,给出用户相应的温馨提示了~下面会有demo
熔断:如果服务器承受了不可承受的压力,或者承受不了的,那么这时候服务器就会雪崩,熔断要做的就是当服务器承受不了或者服务器承受了大于他能承受的了压力,当发生的时候,类似于电量过高,不能在开起来了(在不关闭电线就着火啦),自动跳闸。而hystrix还有自动恢复能力,跳闸的原因是因为服务器压力超出了本身服务器能承受的压力,当压力变小的时候,hystrix就会开启半开启状态,尝试开启。如果压力一直没超出服务器本身压力,那么 “跳闸”,就会自动“跳回去”,恢复正常状态。
干活。
需要依赖的pom
<!-- hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency><!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-conmons</artifactId>
<version>${project.version}</version>
</dependency>
// 注解 下面 web 和actuator 是为了Dashboard 可视化监控provider用到的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.提供者启动类
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableCircuitBreaker
public class PaymentHystrxMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrxMain8001.class,args);
}
//下面是spring升级之后留下的坑,之前一直报错404,借鉴大佬的。熔断和降级不用加,用作是监控提供者的请求,
@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;
}
}
service
@Service
@DefaultProperties(defaultFallback = "paymentInfo_TimeoutHeardler" )//下面两个接口会测试降级,defaultFallback默认回退的方法名字,相当于全局回退,如果@HystrixCommand没单个加了方法名默认回退方法 都会用这个paymentInfo_TimeoutHeardler
public class PaymentService {
@HystrixCommand //(fallbackMethod = "方法名")这里是需要
public String Ok(Integer id){
// int x=10/0; 用来测试的,这里肯定报runtime,
return "线程池 : "+ java.lang.Thread.currentThread().getName()+ " Ok,id:"+id+"\t"+"O(∩_∩)O";
}
//回退方法
public String paymentInfo_TimeoutHeardler(){
return "线程池:"+ java.lang.Thread.currentThread().getName()+ "我是8001提供者 系统出错,或者代码报错,paymentInfo_TimeoutHeardler id"+"\t /(ㄒoㄒ)/";
}
}
controller
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@GetMapping("/payment/ok/{id}")
public String paymentInfo_Ok(@PathVariable("id")Integer id){
return paymentService.Ok(id);
}
}
这里是第一次访问,因为哪个 int x=10/0被注解掉了
下面把注解打开 测试结果下图
很明显,出问题的时候,就会给出相应的提示
下面是熔断demo
修改service
@HystrixCommand(fallbackMethod ="paymentCircuitBreaker_fallback",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"),//失败率达到多少 开启熔断
})
public String paymentCircuitBreaker(@PathVariable("id")Integer id){
if (id < 0){
throw new RuntimeException();
}
return Thread.currentThread().getName()+"\t成功,流水号"+ IdUtil.simpleUUID()+"\t id :" +id;//这个uuid,类似于java里的UUID.randomUUID().toString()只不过去除了 ‘-’
}
public String paymentCircuitBreaker_fallback(@PathVariable("id")Integer id){
return "id 不能为负数 请稍后重试 id : " + id;
}
controller,就是调用了一下service
@Resource
private PaymentService paymentService;
@GetMapping("/circuitbreaker/{id}")
public String CircuitBreaker(@PathVariable("id") Integer id){
return paymentService.paymentCircuitBreaker(id );
}
测试结果 上面的方法加了个 if(id < 0) 就会走降级,第一次输入的是1 所以返回成功 是没问题的,
第二次 输入-1
第三次 输入 2 这里显示的还是成功
没测出来效果 ,为啥
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//时间窗日期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),//失败率达到多少 开启熔断
这两个的意思,就是如果在十秒以内 错误率达到百分之60 才会触发熔断,现在开始输入 -1 并且狂点请求
测试结果下图
输入的是5,逻辑方面肯定是大于0的, 但是跑的还是 降级的方法,
因为熔断开启的时候是不走业务逻辑的。
下面测试自动恢复功能。
当请求开始正常的时候,相当于服务器能承受的压力范围之内了,慢慢就恢复了正常,关闭了熔断。
下面是监控提供者的请求。需要一个监控者9001 新建项目,这里不细说。
9001 pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--eureka client-->
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!--</dependency>-->
<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>
9001 yml
server:
port: 9001
9001主启动
@SpringBootApplication
@EnableHystrixDashboard //这里要加
public class HystrixConsumerMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixConsumerMain9001.class,args);
}
}
三步搞定,如果没问题 访问 localhost:9001
出现这个页面就ok
点击 Monitor Stream
好了,这就实现9001监控8001提供者了,到这里的话,测试就很明显了。
百度很多关于这个界面上的介绍,七色 一圈啦~,
这里就讲两个方便测试,右上方有七个颜色的字
Success | Short-Circuited | Bad Request | Timeout | Rejected | Failure | Error ,
绿色Success 代表请求成功,黑色Error代表请求失败。可以在提供者(8001)测试,输入个正数,和负数,可以看一下这个图的变化,就明白了,如果变化看不出来 就狂请求几次··