透过源码学习设计模式4—HystrixCommand和命令模式

简介:

在面对对象编程中,命令模式是一种行为模式,其中对象用于封装执行动作或稍后触发事件所需的所有信息。这些信息包括方法名称,拥有该方法的对象以及方法参数的值。命令模式也支持可撤销操作。
命令模式包括4个角色:
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。
命令模式有如下优点:
1.降低对象之间的耦合度(将发出请求的对象和执行请求的对象解耦,即将调用者和执行者进行解耦)
2.新的命令可以很容易地加入到系统中。
3.可以比较容易地设计一个组合命令。
4.调用同一方法实现不同的功能
缺点:
可能会导致某些系统有过多的具体命令类。

Hystrix

Hystrix命令模式封装了命令运行逻辑(run)和服务调用失败时回退逻辑(getFallback)。其command抽象类是hystrixcommand,用于包装执行具有潜在风险功能的代码(通常指通过网络进行的服务调用),具备容错和延时,统计和性能指标捕获,断路器和舱壁功能。
该命令本质上是一个阻塞命令,但如果与observe()一起使用,则提供一个可观察的facade。
此模式的详情如下:
  1. 构造Hystrix命令对象,并调用run方法
  2. Hystrix将检查断路器开关是否打开,如果打开,则调用回退方法
  3. 如果断路器开关关闭,Hystrix将检查当前服务的线程池,看是否可以接受新请求。如果线程池已满,则调用回退方法
  4. 如果线程池可以接受新请求,那么Hystrix可以调用run方法来执行run逻辑
  5. 如果run执行失败,则调用回退方法并将健康状态返回到Hystrix指标
  6. 如果run执行超时,则调用回退方法并将健康状况返回到Hystrix指标
  7. 如果run成功执行,则返回正常结果
  8. 如果回退方法成功执行,它将返回回退执行结果
  9. 如果回退方法执行失败,则抛出异常
伪代码示例子
那是否使用命令模式,这两者有什么区别呢?我们通过一些伪代码来帮助理解.
有hystrixcommand之前:
  1. publicclassSimpleHystrix{
  2. privateRestService restService;
  3. privateHttpClientService httpClientService;
  4. privateOkHttpService okHttpService;
  5. publicvoid call(String callName){
  6. if(callName.equals("httpclient")){
  7. httpClientService.do();
  8. }elseif(callName.equals("okhttpclient")){
  9. okHttpService.do();
  10. }elseif(callName.equals("restClient")){
  11. restService.do();
  12. }
  13. }
  14. }
  15. publicclassSimpleHystrixRun{
  16. publicstaticvoid main(String[] args){
  17. SimpleHystrix simpleHystrix =newSimpleHystrix();
  18. simpleHystrix.call("httpclient");
  19. simpleHystrix.call("okhttpclient");
  20. simpleHystrix.call("restClient");
  21. }
  22. }
这里需要根据指令来调用对象的方法,如果需要新增command类型,那么就需要在SimpleHystrix里增加判断,这样SimpleHystrix始终要关注需要调用的外部服务,如果新增服务时需要改动代码,这样违背了面向接口编程的原则,同时代码也较难维护。
有HystrixCommand之后:
如图示,RibbonCommand继承HystrixCommand,它有三个子类
  1. publicclassSimpleHystrix{
  2. privateSimpleHystrixCommand simpleHystrixCommand;
  3. publicvoid setSimpleHystrixCommand(SimpleHystrixCommand simpleHystrixCommand){
  4. this.simpleHystrixCommand = simpleHystrixCommand;
  5. }
  6. publicvoid call(){
  7. simpleHystrixCommand.execute();
  8. }
  9. }
  10. //SimpleHystrixRun为client
  11. publicclassSimpleHystrixRun{
  12. publicstaticvoid main(String[] args){
  13. // 这里service为命令的实际执行者,即Receiver
  14. RestService restService= newRestService();
  15. //simpleHystrix为命令的请求者,即Invoker
  16. SimpleHystrix simpleHystrix =newSimpleHystrix();
  17. //HttpClientRibbonCommand等是具体命令, ConcreteCommand
  18. simpleHystrix.setSimpleHystrixCommand(newHttpClientRibbonCommand(restService));
  19. simpleHystrix.call();
  20. HttpClientServicehttpClientService= newHttpClientService();
  21. simpleHystrix.setSimpleHystrixCommand(newOkHttpRibbonCommand(httpClientService));
  22. simpleHystrix.call();
  23. OkHttpService okHttpService= newOkHttpService();
  24. simpleHystrix.setSimpleHystrixCommand(newRestClientRibbonCommand(okHttpService));
  25. simpleHystrix.call();
  26. }
  27. }
具体执行逻辑在Command中实现,如
ConcreteCommand:
  1. publicclassHttpClientRibbonCommandimplementsSimpleHystrixCommand{
  2. @Override
  3. publicvoid execute(){
  4. //do things
  5. }
  6. }
将服务的实现封装到一个对象委托出去,由命令对象来实现具体的调用。只需要增加一个继承Command的类,然后在execute方法实现对应服务的调用以及其他操作即可,无需侵入业务代码。
本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » 透过源码学习设计模式4—HystrixCommand和命令模式

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多