在以前的文章中,我们介绍过使用Gauva实现限流的功能,现在我们来了解一下如何在服务框架中实现熔断和降级的方法。

简介Hystrix

大型系统架构的演进基本上都是这样一个方向:从单体应用到分布式架构。这个演进过程离不开一个字“拆”,我们会把一个系统拆成很多子系统,子系统之间一定会存在依赖,有的是强依赖(比如Http调用),有的是弱依赖(比如,使用消息中间件)。“拆”的主要意义之一就是一个子系统挂了不影响其他的服务正常运行,而对于那么我们拆出来强依赖的服务如果挂了,还是会影响整个系统,所以我们光“拆”是没有达到效果的。

Hystrix源于Netflix,该库可以对那些在访问远程系统、服务、第三方库或者其他方法调用时所产生的延迟或者故障提供更强大的容错能力。说白了就是提供了一种简洁、灵活和强大的框架去处理依赖异常,一个服务挂了不影响其他的服务正常运行,也是微服务概念中熔断,降级的具体框架实现。

它主要的功能如下:

1.对第三方组件进行访问(特别是网络访问)时出现的延迟或者的异常进行保护和控制。

2.在复杂的分布式系统中,停止级联故障。

3.快速失败,快速恢复。

4.可以优雅的降级。

5.可以提供近实时的监控、告警和操作控制。

典型场景:雪崩效应

Hystrix典型的场景就是处理复杂的分布式调用过程中依赖服务延迟或者异常的场景。下图是一张服务依赖图,用户的请求依赖于跨网络的A、H、I、P四个其他的服务。

如果各个服务运行的都很好,那么不会有问题。在大型系统中,随着服务越来越多,网络或者性能问题引起的超时,逻辑的异常带来的不可访问,都是必然会出现的情况。

如上图,一个用户请求的时候,其中的一个依赖服务I出现了延迟,那么整个的这个用户请求将被阻塞。

随着大量流量的增加,一个单一的后端依赖会成为潜在风险,可能导致整个环境的软硬件资源出现问题。不单单这个服务会挂掉,这些问题还有可能,影响环境中的消息队列、线程等其他资源,从而导致系统上的级联故障。最终出现下图的情况。

网络连接失败或降级,服务和服务器失败或变慢,新的库或服务部署改变行为或性能特征,客户端库有bug等等,所有这些都有可能会造成上述的情况,这就需要我们要隔离和管理这些故障和延迟,以便一个失败的依赖项不能影响整个应用程序或系统。而Hystrix正是解决这类问题的。

Hystrix怎样解决这些问题

1.Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。

2.可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可.当调用超时时,直接返回或执行fallback逻辑。

3.为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。

4.依赖调用结果分:成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。

5.提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。

6.提供近实时依赖的统计和监控

Hystrix把每个潜在的依赖性进行包装,把每一个依赖项都与另一个依赖项隔离开来,当潜在的问题发生时能限制它的资源,并在调用发生异常时能够决定如何应答给调用方,从而快速的恢复处理,不影响下面的调用。如下图,Hystrix对依赖I配置了5个线程。当调用依赖I的时候,Hystrix配置了两种策略,异常和超时,那么只要有一样触发,或者线程被占满,就可以马上进入我们预设的异常处理逻辑。

示例程序HelloWorld

下面我们用一个简单的例子来展示怎样使用Hystrix来处理上面的场景。一个接口调用超过5秒钟或者出现异常的时候,走另外的降级逻辑。

1.pom文件,引用jar包

<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.12</version>
</dependency>

2.使用Hystrix的命令基类HystrixCommand封装调用逻辑,在执行方法体中,我模拟了3种调用结果:分别是正常调用、调用超时(5s)、和接口中出现异常。

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties; import java.util.concurrent.TimeUnit; /**
* 使用HystrixCommand封装执行方法。继承Hystrix命令基类,泛型参数即调用方法的返回参数
*/
public class HelloWorldCommand extends HystrixCommand<String>
{
private final String name; /**
* 定义构造函数,参数即被包装方法的输入参数
* @param name
*/
public HelloWorldCommand(String name)
{
//定义命令组 和 方法调用超时时间
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("HelloWorldGroup"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)));
this.name = name;
} /**
* 封装业务逻辑的方法体,在这里执行真正的业务逻辑。
* @return
* @throws Exception
*/
@Override
protected String run() throws Exception
{
//例子中,模拟执行超时
if (name.equals("TimeoutCommand"))
{
TimeUnit.SECONDS.sleep(6);
}
//例子中,模拟出现异常
if (name.equals("ExceptionCommand"))
{
throw new Exception("ExceptionCommand");
}
//例子中,模拟正常返回
return "Hello " + name + "!";
} /**
* 降级方法定义,即,run方法中出现异常后应该执行的方法。包括例子中的超时。
* @return
*/
@Override
protected String getFallback()
{
return "Command failed!";
}
}

3.调用方法

public class HelloWorld
{
public static void main(String[] args)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String s = new HelloWorldCommand("Nick").execute();
System.out.println(sdf.format(new Date()) + "->" + s); s = new HelloWorldCommand("TimeoutCommand").execute();
System.out.println(sdf.format(new Date()) + "->" + s); s = new HelloWorldCommand("ExceptionCommand").execute();
System.out.println(sdf.format(new Date()) + "->" + s);
}
}

调用方法模拟了3中不同的结果:正常调用、调用超时(5s)、和接口中出现异常。结果如下:

2017-12-24 17:58:18->Hello Nick!
2017-12-24 17:58:23->Command failed!
2017-12-24 17:58:23->Command failed!

Hystrix入门与分析(一):初识Hystrix的更多相关文章

  1. Hystrix入门与分析(二):依赖隔离之线程池隔离

    1.依赖隔离概述 依赖隔离是Hystrix的核心目的.依赖隔离其实就是资源隔离,把对依赖使用的资源隔离起来,统一控制和调度.那为什么需要把资源隔离起来呢?主要有以下几点: 1.合理分配资源,把给资源分 ...

  2. Hystrix入门教程

    Hystrix入门教程 一·什么是Hystrix?Hystrix有什么作用?使用Hystrix有哪些适用场景 Hystrix是springCloud的组件之一,Hystrix 可以让我们在分布式系统中 ...

  3. Hystrix 使用与分析

    转载请注明出处哈:http://hot66hot.iteye.com/admin/blogs/2155036 一:为什么需要Hystrix? 在大中型分布式系统中,通常系统很多依赖(HTTP,hess ...

  4. Spring Cloud实战之初级入门(四)— 利用Hystrix实现服务熔断与服务监控

    目录 1.环境介绍 2.服务监控 2.1 加入依赖 2.2 修改配置文件 2.3 修改启动文件 2.4 监控服务 2.5 小结 3. 利用hystrix实现消费服务熔断 3.1 加入服务熔断 3.2 ...

  5. 断路器之一:Hystrix 使用与分析

    一:为什么需要Hystrix? 在大中型分布式系统中,通常系统很多依赖(HTTP,hession,Netty,Dubbo等),如下图: 在高并发访问下,这些依赖的稳定性与否对系统的影响非常大,但是依赖 ...

  6. [转] Hystrix 使用与分析

    原文地址:http://hot66hot.iteye.com/blog/2155036 转载请注明出处哈:http://hot66hot.iteye.com/blog/2155036 一:为什么需要H ...

  7. Hystrix入门指南

    Introduction 1.Where does the name come from? hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与 ...

  8. SQLite入门与分析(二)---设计与概念(续)

    SQLite入门与分析(二)---设计与概念(续)   写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...

  9. ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 入门案例分析 在第一章里,我们已经对ArcGIS系列软件的体系结构有了一 ...

随机推荐

  1. Java第一章

    第一章 计算机程序:计算机为完成某些功能产生的一系列有序指令集合. Java技术包括:JavaSE(标准版)  JavaEE(企业版) ---JavaME(移动版) 开发Java程序步骤:1.编写 2 ...

  2. jQuery 学习04——遍历:定义、向上、向下、同级、过滤

    Query 遍历,意为"移动",用于根据其相对于其他元素的关系来"查找"(或选取)HTML 元素. 以某项选择开始,并沿着这个选择移动,直到抵达您期望的元素为止 ...

  3. Mybatis : "less than" issue in Select annotations

    I am using java7, spring 3 and mybatis Pom.xml <org.mybatis-version>3.2.8</org.mybatis-vers ...

  4. ABAP非Unicode系统中字符串拼接(CONCATENATE)时吃字符问题

    系统是老R3,非Unicdoe系统,某些表字段是从外界系统过来的,由于接口设计的固定长度,外界系统传超长字符串过来后,就可能从最后一个中文字符中间截断,这问题到还没什么,只不过显示时最后一个字符显示成 ...

  5. 【JVM】垃圾收集器

    程序计数器.Java虚拟机栈.本地方法栈分配的内存是确定的,生命周期与线程同样.所以不须要过多考虑回收问题. 而Java堆和方法区仅仅有运行时才知道有哪些对象被创建,须要多少内存,这部分的内存分配和回 ...

  6. mysql导入自定义函数不成功的解决方法

    进入mysql控制台:mysql -uroot -p set global log_bin_trust_function_creators=1;

  7. wsl install lamp

    sudo apt-get update sudo apt-get install lamp-server^ /etc/init.d/apache2 start /etc/init.d/mysql st ...

  8. 【.NET 深呼吸】.net core 中的轻量级 Composition

    记得前面老周写过在.net core 中使用 Composition 的烂文.上回老周给大伙伴们介绍的是一个“重量级”版本—— System.ComponentModel.Composition.应该 ...

  9. dubbo配置多个注册中心

    用法: <dubbo:registry address="zookeeper://10.0.1.131:2181?backup=10.0.1.132:2181,10.0.1.133:2 ...

  10. 最新的Delphi版本号对照

    The CompilerVersion constant identifies the internal version number of the Delphi compiler. It is de ...