断路器Hystrix
Posted Lmg12580
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了断路器Hystrix相关的知识,希望对你有一定的参考价值。
分布式系统面临的问题
服务雪崩
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
Hystrix能干什么?
服务降级、服务熔断、服务限流、服务监控
题外话:hystrix直译为豪猪,是一种背上长满刺的动物,跟刺猬一样,也不知道老外为啥取了这么个名字。同属于Netflix公司下的产品,一样的优秀,目前也停更进维,国内使用还是比较多的,所以也得学。但是目前阿里推出了sentinel,流行趋势很大,估计以后都要换了,在后续推出的Cloud Alibaba篇会详细介绍。
不让客户端等待并立刻返回一个友好提示,如服务器繁忙,请稍后再试。
程序运行异常
超时
服务熔断触发服务降级
线程池/信号量打满
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
Hystrix既可以放在消费端,也可以放在服务提供端,没有严格意义上的要求,但是一般工作中放在消费端的比较多。为了学习,下面在消费方和服务方都配一下。
一、新建两个工程
1. 服务提供者pom文件添加Hystrix的依赖包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2. 修改yml文件如下
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka8761.com:8761/eureka
3. 新增PaymentService.java类,添加方法
@Service
public class PaymentService {
public String paymentInfoTimeOut(Integer id) {
try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); }
return "线程池:" + Thread.currentThread().getName() + " paymentInfoTimeOut,id:" + id + " :)";
}
}
4. 新增PaymentController.java类,添加方法
@RestController
public class PaymentController {
@Resource
private PaymentService paymentService;
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfoTimeOut(@PathVariable("id") Integer id){
return paymentService.paymentInfoTimeOut(id);
}
}
1. pom文件添加Hystrix依赖,同上
2. 修改yml配置
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka8761.com:8761/eureka
ribbon:
ReadTimeout: 5000 #指的是建立连接所需要的时间
ConnectTimeout: 5000 #指的是建立连接后从服务器读取到可用资源所用的时间
3. 主启动类
@SpringBootApplication
@EnableFeignClients
public class OrderHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(OrderHystrixApplication.class, args);
}
}
4. 新增PaymentHystrixService.java接口,用来远程调用支付服务
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService {
@GetMapping("/payment/hystrix/timeout/{id}")
String paymentInfoTimeOut(@PathVariable("id") Integer id);
}
5. 新增OrderHystrixController.java类
@RestController
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/hystrix/timeout/{id}")
public String paymentInfoTimeOut(@PathVariable("id") Integer id){
return paymentHystrixService.paymentInfoTimeOut(id);
}
}
以上两个工程搭建完以后,启动eureka及这两个服务,浏览器测试能否调通,如果出现如下内容则搭建成功(为了方便测试,后续将eureka集群的配置去掉,使用单节点的配置)。
在服务提供者端使用
服务端使用服务降级的目的,主要是为了确保提供方的接口无误,只有上游的接口正确,才能保证链路的稳定性。服务降级核心注解@HystrixCommand
1. 修改service方法,在要加服务降级的方法上添加@HystrixCommand注解,注解内指定在调用当前方法失败后的fallback方法,该方法需要我们手动编码实现,同时给接口设置1秒的超时时间,意思就是如果调用此接口超过1秒,则会启用服务降级。
2. 主启动类添加注解:
@EnableCircuitBreaker
还有一个小细节就是我们注意这时候他的工作线程是Hystrix内置的,已经不是tomcat的线程了。
-
在消费端使用
2. 改完后主启动类添加启用注解(别忘了),启动消费端,浏览器测试,可以发现消费端超过两秒后自动走到了fallback方法。
-
全局服务降级
1. 在消费端controller类上面加此注解
通配服务降级FeignFallback
@Component
public class PaymentFallbackService implements PaymentHystrixService{
@Override
public String paymentInfoTimeOut(Integer id) {
return "PaymentFallbackService fallback";
}
}
2. yml文件添加以下内容
#用于服务降级在注解@FeignClient中添加fallbackFactory属性值
feign:
hystrix:
enabled: true
3. feign接口中指定fallback类
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
1. 修改服务提供者8001,添加以下代码,重点是注解内的四个参数,这个配置的意思就是说,在10秒内请求10次,如果有6次失败,则打开断路器
PaymentService.java
@HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallback",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(Integer id){
if (id < 0){
throw new RuntimeException("id不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+ " "+"调用成功,流水号:"+serialNumber;
}
public String paymentCircuitBreakerFallback(Integer id){
return "id不能为负数,请重试~ id:"+id;
}
PaymentController.java
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
return paymentService.paymentCircuitBreaker(id);
}
a. id先输入正数,正常返回
b. id输入负数,报错
c. id输入负数,疯狂加载几次,再输入正数,报错。这时“1”明明正数,却报错,说明这时候断路器被打开了,我们走的是fallback方法
d. id输入正数,多加载几次,慢慢的就正常返回
总结:
熔断打开:请求不再进行调用当前微服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。
熔断关闭:熔断关闭不会对服务进行熔断。
三、服务限流
四、服务监控Dashboard
2. 添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3. 修改yml文件
server:
port: 9001
hystrix:
dashboard:
proxy-stream-allow-list: "*"
4. 主启动类添加开启注解
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
http://localhost:9001/hystrix
a. 如果需要监控服务提供类,则被监控的服务必须有以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
b. 被监控服务主启动类添加如下代码,此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
@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;
}
7. 请求一下8001的熔断接口,就上面测得正负数的那个,然后点击Monitor Stream,进入仪表盘
该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。
tips:dashboard可以同时监控多个服务,所有服务都会在这里展示出来。
到这里,Hystrix的基本知识就学习完了
接下来开始学习下个组件:新一代路由网关GateWay
以上是关于断路器Hystrix的主要内容,如果未能解决你的问题,请参考以下文章
springCloud Finchley 微服务架构从入门到精通断路器 Hystrix(feign)