这是本人学习的总结,主要学习资料如下
- 马士兵教育
- 1、Hystrix简介
- 2、Hystrix架构
- 2.1、Hytrix的入口
- 2.2、toObservable()流程
- 3、Hsytrix的简单样例
- 3.1、dependency
- 3.2、代码样例
1、Hystrix简介
Hytrix是用于处理处理延迟和容错的开源库,包含服务隔离,服务熔断、服务降级,限流等功能。
- 服务隔离:当一个服务出问题时,保证问题不会扩散到其他模块。
- 服务熔断:服务熔断一般和服务降级一起使用,当服务发生错误时,快速告诉服务调用者该服务不可用,免得调用者花额外的时间等待。
- 限流:流量超出预期时,统一处理额外的流量。
他是给服务提供者使用的组件。利用Hystrix
我们可以快速简单地实现上面提到的功能。
2、Hystrix架构
以上是Hytrix
的架构图。
内部它维护着线程池来处理服务请求,在此过程中也维护着一些变量和一些设计模式来实现限流,服务降级等功能。
服务端接到请求后,只需要简单地拿到HystrixCommand
或HystrixObservableCommand
对象(可以作为bean
在Spring容器中维护),然后通过这个对象调用服务就能轻松实现Hystrix
支持的功能。
2.1、Hytrix的入口
左上是Hytrix
的入口,请求服务者的所有请求最终都会被包装成HytrixCommand
和HytrixObservabeCommand
这两个中的一个。
他们暴露了四个方法去请求服务execute()
,queue()
,observe()
和toObservable()
。这四个方法大同小异,不过最终真正去执行请求服务的操作都是toObservable()
方法,其他三个方法不过是同步异步,阻塞式非阻塞式的不同而已。
2.2、toObservable()流程
上面提到toObservable()
才是真正执行请求的方法,我们来看看他具体做了什么。
- 查看请求的服务是否有缓存的结果,有则返回,没有继续。
- 查看服务熔断器(
Circuit Breaker
)是否开启,如果开启证明该服务提供者没有能力提供服务,可以直接跳到拒绝服务的getFallback()
或resumeWithFallback()
节省时间。 - 查看服务者的线程池是否有余力处理请求。如果没有则开启熔断器以拒绝后续的更多请求,同时跳转到
getFallback()
或resumeWithFallback()
;如果有则放到线程池的请求列表等待分配线程处理请求。 - 正常分配线程提供服务,如果出错就开启熔断器并跳转到
getFallback()
或resumeWithFallback()
。 - 查看处理请求是否超时,如果超时则开启熔断器并跳转到
getFallback()
或resumeWithFallback()
。 - 正常返回服务结果。
3、Hsytrix的简单样例
3.1、dependency
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
</dependency>
3.2、代码样例
这里用HystrixCommand
做示例。
因为Hystrix
是通过线程池处理业务逻辑,所以我们要先实现HystrixCommand
,业务逻辑写在run()
方法里。
构造方法里的逻辑不用深究,示例中传入的魔法值command
没有任何功能上的意义,他只是一个名字,标识这个HystrixCommand
。
@Component
public class CommandDemo extends HystrixCommand<String> {
public CommandDemo() {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("command")));
}
@Override
protected String run() throws Exception {
// 模拟业务逻辑
String result = "Hello, World! I'm " + name;
return result;
}
}
在Controller那里拿到这个CommandDemo
对象,直接执行就行。使用起来就像是在调用普通的Service方法。之后我们可以通过配置等方式简单地完成限流等功能。
@RestController
public class UserController {
@Autowired
private CommandDemo commandDemo;
@GetMapping("/getUserInfo")
public String getUser() {
String execute = commandDemo.execute();
System.out.println(execute);
return execute;
}
}