Netflix Hystrix 断路器或者熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
Hystrix 是一个延迟和容错库,旨在隔离对远程系统、服务和第 3 方库的访问点,停止级联故障并在故障不可避免的复杂分布式系统中实现弹性。
作用:
- 保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。
- 快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。
- 提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。
- 防止故障扩散:使用熔断机制,防止故障扩散到其他服务。
- 监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。
hystrix提供了熔断和降级。
降级
降级其实就相当于,当我们向一个服务发起请求,当请求超时了,就会把这次请求记录到服务中,然后就会尝试向其他服务发请求,如果还没成功,就对这次请求进行处理(怎么处理取决于业务需求如)就相当于try catch一样的逻辑,当然hystrix底层使用aop来实现的。
隔离和限流
每当向服务发起一个请求时,就是会发起一个http请求,每一个http请求就要开启一个线程,然后等待服务返回信息,这容易导致线程的堆积,所以就可以用http的URI作为一个标识,然后相同的URI可以开启一个线程池,然后线程池中限定线程数,这样就可以设置拒绝策略,当线程池满了,就可以快速的抛出异常或者拒绝请求,用线程池做到线程隔离来达到限流。
熔断
熔断就是有一个阈值,向服务发起请求后,如果不成功,就会记录次数,然后当连续失败次数达到阈值时,下次请求的时候就会直接把这个服务停止。请求有三种状态,可以请求(开),不可请求(关),还有一个中间状态,相当于半开状态,半开状态是什么意思呢,就是可以尝试着去请求,就可以在关闭状态后一段时间,发一个请求尝试一下是否可以请求成功,如果是吧,继续保持关闭状态,如果请求成功,则变成开放状态。
我们还是继续前面的工程进行改造
1.首先我们需要在消费端增加依赖
org.springframework.cloud spring-cloud-starter-netflix-hystrix
2.在前面写的TestController类中我们需要在方法上增加
- @HystrixCommand注解并指定回调方法,
- 特别注意,这里和方法的返回类型,参数类型要一致
- fallBack方法的参数要跟你注解的方法参数保持一致,否则会报错。
- 而且两个方法必须要在同一个类中,由于在同一个类中,所以fallBack的修饰符没有限制
package com.studycloud.eurekaclientproducer;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
TestInterface testInterface;
public String fallBack(){
return "熔断起作用,调用熔断解决方案";
}
@RequestMapping("/test")
@HystrixCommand(fallbackMethod = "fallBack")
public String test(){
String result = testInterface.test();
return result;
}
}
这里附上TestInterface的代码
package com.studycloud.eurekaclientproducer;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name = "eureka-service-provider")//eureka-service-provider是提供者的服务名称
public interface TestInterface {
@RequestMapping("/test")
public String test();
}
3.在启动类上需要添加一个@EnableCircuitBreaker注解
package com.studycloud.eurekaclientproducer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker
public class EurekaClientProducerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProducerApplication.class, args);
}
}
这里附上配置文件
eureka:
client:
serviceUrl: #注册中心的地址
defaultZone: http://localhost:8761/eureka/
server:
port: 8764 #服务端口号
spring:
application:
name: eureka-service-consumerA #提供者的服务名称
4.我们来看下Erueka的管理吧,看下正在启动的项目
两个服务提供者,一个消费者
5.访问消费者,正常以轮询的方式进行访问。
6.我将提供者B服务关掉(代表服务有问题)现在获取A没有问题,
7.获取服务B的时候可以看出已经走了咱们写的回调函数
8.再等会发现,只会调用服务A,而不会调用服务B ,这是Eureka起作用呢
9.我们继续将服务B启动,等一会以后 有连接到了服务B
10.其实这里我们在启动类上加了一堆注解
11.这里我们可以将注解缩减,使用@SpringCloudApplication注解,其实原理很简单他包含了其他几个注解。
12.所以精简以后就变成了
package com.studycloud.eurekaclientproducer;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringCloudApplication
@EnableFeignClients
public class EurekaClientProducerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProducerApplication.class, args);
}
}



