在微服务架构中我们需要将系统拆分成很多服务单元,各单元的应用通过服务注册与订阅的方式互相依赖,依赖通过远程调用的方式执行,这样会由于网络原因或服务自身问题出现调用故障或延时,导致调用方也延迟,然后这样慢慢任务挤压,导致服务瘫痪。一个单元的故障可能会蔓延到其他一大片服务的故障,架构相对不稳定,所以需要断路器等一系列保护机制,通过断路器的故障监控,当服务出现问题时,调用方会立马返回一个错误响应而不是长时间的阻塞,避免故障蔓延等。
Hystrix提供了断路器、线程隔离等一系列服务保护功能,它通过控制那些访问远程系统、服务和第三方库的节点从而对延迟和故障提供更大的容错能力,Hystrix提供服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并、服务监控等强大功能.
// fallbackMethod 指定错误后的回调方法名称.
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloFallback")
public String helloService() {
restTemplate.getForEntity();
}
public String helloFallback() {
return "error"
}
}
工作流程:
1.创建HystrixCommand或HystrixObservableCommand对象用来表示对依赖服务的操作请求,同时传递所需要的参数.采用了"命令模式"来实现对服务调用操作的封装
// 顺便结合学习下命令模式: 它将来自客户端的请求封装成对象,从而让你可以使用不同的请求对客户端进行参数化,用来实现对请求者和实现者的解耦.
// 1
public class Receiver {
public void action() {
}
}
interface Command {
void execute();
}
// 2
public class ConcreteCommand implements Command{
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
this.receiver.action();
}
}
// 3
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action() {
this.command.execute();
}
}
// 4
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.action();
}
}
// 最后 ! 我没有学会这个命令模式, 我不知道为什么要用命令模式 - -
HystrixCommand:用在依赖的服务返回单个操作结果的时候
HystrixObservableCommand:用在依赖的服务返回多个操作结果的时候
资源隔离(线程池隔离和信号量隔离)机制:限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其它服务调用。(隔离机制区别参考:https://blog.youkuaiyun.com/liuchuanhong1/article/details/73718794) 大致是响应快的用信号量,慢的用线程池.
限流机制:限流机制主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。
熔断机制:当失败率达到阀值自动触发降级(如因网络故障、超时造成的失败率真高),熔断器触发的快速失败会进行快速恢复。
降级机制:超时降级、资源不足时(线程或信号量)降级 、运行异常降级等,降级后可以配合降级接口返回托底数据。
缓存支持:提供了请求缓存、请求合并实现
通过近实时的统计/监控/报警功能,来提高故障发现的速度
通过近实时的属性和配置热修改功能,来提高故障处理和恢复的速度
Hystrix是如何实现它的目标的?
(1)通过HystrixCommand或者HystrixObservableCommand来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,资源隔离
(2)对于超出我们设定阈值的服务调用,直接进行超时,不允许其耗费过长时间阻塞住。这个超时时间默认是99.5%的访问时间,但是一般我们可以自己设置一下
(3)为每一个依赖服务维护一个独立的线程池,或者是semaphore,当线程池已满时,直接拒绝对这个服务的调用
(4)对依赖服务的调用的成功次数,失败次数,拒绝次数,超时次数,进行统计
(5)如果对一个依赖服务的调用失败次数超过了一定的阈值,自动进行熔断,在一定时间内对该服务的调用直接降级,一段时间后再自动尝试恢复
(6)当一个服务调用出现失败,被拒绝,超时,短路等异常情况时,自动调用fallback降级机制
(7)对属性和配置的修改提供近实时的支持
参考原文:https://blog.youkuaiyun.com/sun_qiangwei/article/details/80376701