Spring Boot版本:2.1.4.RELEASE

Spring Cloud版本:Greenwich.SR1

前述:

​ 在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进行中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身的问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会因为等待出现故障的依赖方响应形成任务积压,最终导致自身服务的瘫痪。

​ 举一个例子,在一个电商网站中,我们可能会将系统分成用户,订单,库存,积分,评论等一系列的服务单元。用户创建一个订单的时候,客户端将调用订单服务的创建订单接口,此时创建订单接口又会向库存服务来请求出货。此时若库存服务因自身处理逻辑等原因造成响应缓慢,会直接导致创建订单服务的线程被挂起,以等待库存申请服务的响应,在漫长的等待之后用户会因为请求库存失败而得到创建订单失败的结果,如果在高并发的情况下,因这些挂起的线程在等待库存服务的响应而未能释放,使得后续到来的创建订单请求被阻塞,最终导致订单服务也不可用。

​ 在微服务架构中,存在那么多的服务单元,若一个单元出现故障,就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加的不稳定,为了解决这样的问题,产生了断路器等一系列的服务保护机制。

​ 当某个服务发生故障后,通过断路器的故障监控,向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

​ 针对上述问题,Spring Cloud Hystrix实现了断路器,线程隔离等一系列服务保护功能。它也是基于Netflix的开源框架Hystrix实现的,该框架的目标在于通过控制那些访问远程系统,服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备服务降级,服务熔断,线程和信号隔离,请求缓存,请求合并以及服务监控等强大功能。

快速入门:
  1. 如何使用hystrix:

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
  2. 使用示例:

    @RestController
    @RequestMapping("/consumer")
    @RequiredArgsConstructor
    public class Controller { private final RestTemplate ribbonRestTemplate; @GetMapping("/get")
    @HystrixCommand(fallbackMethod = "fallback")
    public String consume() {
    ResponseEntity<String> responseEntity = ribbonRestTemplate
    .getForEntity("http://EUREKA-CLIENT/client/hello?who=小王",
    String.class);
    System.out.println(responseEntity.getBody());
    return responseEntity.getBody();
    }
    // 当调用失败时(服务器发生异常)或者超出断路器最大等待时间,会执行这个回调方法
    public String fallback() {
    return "error";
    }
    }
命令模式:

先看下Nystrix官网的流程图,我们根据图中标志的顺序来解析每个环节

  1. 首先,创建一个HystrixCommand或者HystrixObservableCommand对象

    首先,创建一个HystrixCommand或者HystrixObservableCommand对象用来表示对依赖服务的操作请求,同时传递所有需要的参数。从其命名我们就知道它是采用了”命令模式“来实现对服务调用操作的封装。而这两个command对象分别针对不同的应用场景

    • HystrixCommand:用在依赖的服务返回单个操作结果的时候
    • HystrixObservableCommand:用在依赖的服务返回多个操作结果的时候

    什么是命令模式?

    将来自客户端的请求封装成一个对象,从而可以让你使用不同的请求对客户端进行参数化。它可以被用于实现“行为请求者”与“行为实现者”的解耦,以便使两者可以适应变化。

    我们需要知道:

    1. 命令模式是通过命令发送者和命令执行者的解耦来完成对命令的具体控制的。
    2. 命令模式是对功能方法的抽象,并不是对对象的抽象。
    3. 命令模式是将功能提升到对象来操作,以便对多个功能进行一系列的处理以及封装。

经典的命令模式包括4个角色:

  1. Command:定义命令的统一接口
  2. ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
  3. Receiver:行为实现者
  4. Invoker:行为请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。

先看下示例代码,我们再来分析这个设计模式:

/**
* 定义命令的统一接口
*
* @author dmz
* @date Create in 16:18 2019/5/18
*/
public interface Command {
/**
* 定义命令的抽象执行策略
*/
void execute();
} /**
* Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
*
* @author dmz
* @date Create in 16:18 2019/5/18
*/
public class ConcreteCommand implements Command { private Receiver receiver; public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
} @Override
public void execute() {
receiver.action();
}
} /**
* 行为请求者
*
* @author dmz
* @date Create in 16:37 2019/5/18
*/
public class Invoker {
/**
* 行为请求者要持有需要请求的命令
*/
private Command command; public void setCommand(Command command) {
this.command = command;
} /**
* 行为请求者发起命令
*/
public void invoke() {
System.out.println("发起命令");
command.execute();
}
} /**
* 行为实现者
*
* @author dmz
* @date Create in 16:22 2019/5/18
*/
public class Receiver {
public void action() {
System.out.println("执行业务逻辑");
}
} /**
* @author dmz
* @date Create in 16:38 2019/5/18
*/
public class Main {
public static void main(String[] args) {
Command concreteCommand = new ConcreteCommand(new Receiver());
Invoker invoker = new Invoker();
invoker.setCommand(concreteCommand);
invoker.invoke();
}
}

​ 从上面的示例中,我们可以看到Invoker跟Receiver通过Command接口实现了解耦。对于调用者来说,我们可以为其注入多个命令操作,比如新建文件,复制文件,删除文件这样三个操作,调用者只需要在需要的时候直接调用即可,而不需要知道这些操作命令实际是如何实现的。

​ 关于命令模式,我们一直要知道它设计的初衷是什么,否则就会很混乱,每一个设计模式的出现都是为了解决特定情况下的某些问题,而不是凭空想象出来的,我们要能在合适的场景取采用合适的模式才算真正理解了这种设计模式。命令模式的初衷就是为了实现:对命令请求者(Invoker)和命令实现者(Receiver)的解耦,方便对命令进行各种控制。

在下面这些情况应考虑使用命令模式:

  1. 使用命令模式作为“回调(CallBack)”在面向对象系统中的替代,“CallBack”讲的便是先将一个函数登记上,然后在以后调用此函数。
  2. 需要在不同的时间指定请求,将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原生的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以是在网络的另外一个地址上。命令对象可以在序列化后传送到另外一台机器上去
  3. 系统需要支持命令的撤销。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令对象所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时再重新实现命令效果。
  4. 如果要将系统中所有的数据更新到日志里,以便在系统奔溃时,可以根据数据读回所有的数据更新命令,重新调用Execute()方法一条条执行这些命令,从而恢复系统在奔溃前所作的数据更新
RxJava:

​ 在Hystrix的底层实现中,大量的使用了RxJava,为了更容易的理解后续内容,在这里对RxJava的观察者-订阅者模式做一个简单的入门介绍。

RxJava 有以下三个基本的元素:

  1. 被观察者(Observable):

    • 用来向订阅者Subscriber对象发布事件,Subscriber对象则在接受到对象后对其进行处理,而在这里指的事件通常就是对依赖服务的调用。
    • 一个被观察者可以发出多个事件,知道结束或者发生异常。
    • Observable对象每发出一个事件,就会调用对应观察者subscribe对象的onNext()方法
    • 每一个Observable的执行,最后一定会通过调用subscribe.onCompleted()或者subscribe.onError()来结束该事件的操作流
  2. 观察者(Observer):
  3. 订阅(subscribe)

Spring Cloud学习 之 Spring Cloud Hystrix(基础知识铺垫)的更多相关文章

  1. Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)

    Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...

  2. Spring Cloud 学习 之 Spring Cloud Eureka(搭建)

    Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 文章目录 搭建服务注册中心: 注册服务提供者: 高可用注册中心: 搭建服务注册中心: ...

  3. 学习 shell脚本之前的基础知识

    转载自:http://www.92csz.com/study/linux/12.htm  学习 shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写sh ...

  4. 【转载】salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句

    salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句 salesforce如果简单的说可以大概分成两个部分:Apex,VisualForce Page. 其中Apex ...

  5. Spring Cloud学习笔记--Spring Boot初次搭建

    1. Spring Boot简介 初次接触Spring的时候,我感觉这是一个很难接触的框架,因为其庞杂的配置文件,我最不喜欢的就是xml文件,这种文件的可读性很不好.所以很久以来我的Spring学习都 ...

  6. spring cloud学习(六)Spring Cloud Config

    Spring Cloud Config 参考个人项目 参考个人项目 : (希望大家能给个star~) https://github.com/FunriLy/springcloud-study/tree ...

  7. Spring Cloud 学习 (九) Spring Security, OAuth2

    Spring Security Spring Security 是 Spring Resource 社区的一个安全组件.在安全方面,有两个主要的领域,一是"认证",即你是谁:二是& ...

  8. Spring Boot学习笔记---Spring Boot 基础及使用idea搭建项目

    最近一段时间一直在学习Spring Boot,刚进的一家公司也正好有用到这个技术.虽然一直在学习,但是还没有好好的总结,今天周末先简单总结一下基础知识,等有时间再慢慢学习总结吧. Spring Boo ...

  9. Spring.NET学习笔记1——控制反转(基础篇)

    在学习Spring.NET这个控制反转(IoC)和面向切面(AOP)的容器框架之前,我们先来看一下什么是控制反转(IoC). 控制反转(Inversion of Control,英文缩写为IoC),也 ...

  10. Spring 框架学习(1)--Spring、Spring MVC扫盲

    纸上得来终觉浅,绝知此事要躬行 文章大纲 什么是spring 传统Java web应用架构 更强的Java Web应用架构--MVC框架 Spring--粘合式框架 spring的内涵 spring核 ...

随机推荐

  1. MAC 上brew 更新 出错

    在MAC上brew update的时候出现报错:Error: /usr/local must be writable! 错误,在该文章中也给出解决办法(sudo chown -R $(whoami) ...

  2. hexo部署在码云中 无样式问题

    在本地localhost:4000 运行如下 上传码云之后打开Gitee Pages服务 如下 同时控制台打印 解决方法 找到根目录下的_config.yml中的url 和 root # url: h ...

  3. 给学妹的 Java 学习路线

    大家好,这篇文章主要是讲解下如何自学 Java,这个问题有很多粉丝私信问过,今天又有直系学妹问我如何学习 Java? 我就以我的经历,总结下分享给大家,有不当指出或者有更好的方法建议也欢迎留言指出,大 ...

  4. win10安装docker,VSCode管理docker

    背景 docker:随着技术的不断迭代,开发环境的配置与部署越来越重要.Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linu ...

  5. Java数组 —— 八大排序

    (请观看本人博文--<详解 普通数组 -- Arrays类 与 浅克隆>) 在本人<数据结构与算法>专栏的讲解中,本人讲解了如何去实现数组的八大排序. 但是,在讲解的过程中,我 ...

  6. Springboot:定时任务处理(十三)

    构建一个定时任务的service接口及实现(模拟) 接口:com\applesnt\springboot\service\TaskService.java package com.applesnt.s ...

  7. 漫谈LiteOS-端云互通组件-MQTT开发指南(下)

    1.介绍 SDK简介 Agent Tiny是部署在具备广域网能力.对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件,您只需调用API接口,便可实现设备快速接入到物联网平台以及数据上报 ...

  8. Python 如何实现 单实例

    出处:https://stackoverflow.com/questions/380870/make-sure-only-a-single-instance-of-a-program-is-runni ...

  9. windows下怎么同时使用python2和3

    windows命令行下,怎么能够自由的切换python2和3呢?当然不是切换目录!很多帖子告诉你,将python2目录下的python.exe文件改成python2.exe,pyhton3目录下的py ...

  10. git常用命令/git 部分高级命令备忘录

    常用命令 克隆 - git clone  git@gitee.com:niunafei1/git_learning.git git 创建分支 - git checkout -b dev git 切换分 ...