SpringCloud断路器
Hystrix
简介
hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制。
这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo。
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。
Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用
什么是断路器
Hystrix重要概念
服务降级
简单来说,就是对方系统不可用了,你需要给我一个兜底的解决方法
服务降级是指在系统负载过高或者出现异常情况时,通过减少或关闭某些服务功能,来保证系统的稳定性和可用性。服务降级可以有效地避免系统崩溃或者无法响应的情况,同时也可以保证系统的核心功能能够正常运行。在实际应用中,服务降级通常是通过设置优先级、限流、熔断等方式来实现的。
哪些情况会触发降级:
- 程序运行异常
- 超时
- 服务熔断
- 线程池/信号量打满
服务熔断
服务熔断是一种微服务架构中的容错机制,用于保护系统免受服务故障的影响。当一个服务出现故障或响应时间过长时,熔断器会自动断开该服务的调用,并返回一个预设的错误响应,从而避免请求在该服务上长时间阻塞。这样可以减少系统的响应时间和资源消耗,同时也可以防止故障服务的连锁反应,提高系统的可用性和稳定性。服务熔断通常与服务注册与发现、负载均衡等技术一起使用,是构建高可用、弹性和可靠的分布式系统的重要手段之一。
类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,让后调用服务降级的方法并返回友好提示
服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
服务限流是一种控制系统或应用程序流量的技术,它可以限制系统或应用程序接受的请求数量,以避免系统或应用程序过载或崩溃。服务限流通常用于保护系统或应用程序免受恶意攻击或过度使用的影响。它可以通过限制每个用户的请求速率、限制每个IP地址的请求速率或限制整个系统的请求速率来实现。服务限流可以帮助系统或应用程序更好地处理高负载情况,提高系统的可用性和稳定性。
分布式系统面临的问题
服务雪崩
Hystrix案例实战!
新建项目cloud-provider-hystrix-payment8003
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
修改yml文件
server:
port: 8003
spring:
application:
name: cloud-provider-hystrix-payment
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db2019?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
eureka客户端,启动!
Hystrix,启动!
==
==
没有问题,启动成功
新建moudle
cloud-consumer-feign-hystrix-order80
pom:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
yml:
server:
port: 8005
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:7001/eureka
spring:
main:
#允许存在多个Feign调用相同Service的接口
allow-bean-definition-overriding: true
服务降级
@HystrixCommand
设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有兜底的方法处理,作服务降级fallback
不要忘了主启动类加上注解: @EnableHystrix
超过了3s,直接返回我们定义的页面
当我们在程序中间加入: int age = 10/0
系统就不会等待3s,而是直接输出错误页面
客户端开启服务降级
yml:
feign:
hystrix:
enabled: true
客户端代码:
全局服务降级DefaultProperties
目前的问题:每个业务方法都有对应的一个兜底的方法–代码膨胀
第一步:在类上添加注解
第二步:在方法上写注解
这样解决了代码膨胀的问题
服务熔断
熔断机制概述:
熔断机制是应对雪崩效应的一种微服务链路保护机制
当扇出链路的某个微服务出错或响应时间过长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回错误的响应信息
而当检测该节点微服务调用响应正常的时候,就应当恢复调用链路
Spring Cloud框架里,熔断机制通过Hystrix实现 其会监控微服务之间的调用情况
比如出现5s内20次失败调用,就会触发熔断机制
熔断机制的注解是@HystrixCommand
//这里是服务熔断的相关代码
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//是否开启断路器?开启
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//置Hystrix熔断器的请求阈值为10,即当在一个统计窗口内处理的请求总数达到10个时,才会触发熔断器的开启操作。
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliSeconds",value = "10000"),//表示在熔断器打开后,等待多长时间后尝试再次请求服务。这里设置的是10秒。
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//失败率达到多少跳闸
})
//这里是服务熔断的相关代码
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//是否开启断路器?开启
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//置Hystrix熔断器的请求阈值为10,即当在一个统计窗口内处理的请求总数达到10个时,才会触发熔断器的开启操作。
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//表示在熔断器打开后,等待多长时间后尝试再次请求服务。这里设置的是10秒。
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//失败率达到多少跳闸
})
@GetMapping("/consumer/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
if (id < 0){
throw new RuntimeException("id不能为负数!");
}
String serialNumber = String.valueOf(UUID.randomUUID());
return "gg";
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
return "id不能为负数,请重试";
}
对于上述代码,如果我们在浏览器输入的id为负数,多次刷新浏览器,就会触发服务熔断,因为失败次数过多,这个时候,在熔断器时间窗口期内,即使我们输入的id为正数,也会输出fallback页面,直到时间窗口期外,熔断器进入半熔断状态,正确访问才会显示页面gg
服务监控hystrixDashboard
新建模块cloud-consumer-hystrix-dashboard9001
依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
yml:
server:
port: 9001
spring:
application:
name: cloud-monitor-hystrix
datasource:
url: jdbc:mysql://127.0.0.1:3306/db2019?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
启动类:
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class hystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(hystrixDashboardMain9001.class);
}
}
浏览器输入:
接着,我们在熔断器类(端口号8005)启动类下写代码:
@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;
}
==
很好玩
==
技术这条路,道阻且长~~~