在以前的文章中,我们介绍过使用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. 【二分图最大匹配】Bullet @山东省第九届省赛 B

    时间限制: 6 Sec 内存限制: 128 MB 题目描述 In GGO, a world dominated by gun and steel, players are fighting for t ...

  2. Atcoder4105 Same Integers(模拟)

    https://abc093.contest.atcoder.jp/tasks/arc094_a?lang=en 思路题还是不太会做哈.感觉数据不大,一开始dfs做但是发现不是最优解,一想确实是这么一 ...

  3. [Java代码] Java用pinyin4j根据汉语获取各种格式和需求的拼音

    pinyin4j是一个功能强悍的汉语拼音工具包,主要是从汉语获取各种格式和需求的拼音,功能强悍,下面看看如何使用pinyin4j.下面介绍用pinyin4j来做的一个根据汉语获取各种格式和需求的拼音d ...

  4. Android_Printservice_API_部分翻译

    文件夹 * package android.printservice * public abstract class PrintService * public abstract class Prin ...

  5. SSE图像算法优化系列十九:一种局部Gamma校正对比度增强算法及其SSE优化。

    这是一篇2010年比较古老的文章了,是在QQ群里一位群友提到的,无聊下载看了下,其实也没有啥高深的理论,抽空实现了下,虽然不高大上,还是花了点时间和心思优化了代码,既然这样,就顺便分享下优化的思路和经 ...

  6. HashSet代码分析

    HashSet (jdk 1.7)的继承关系如下: HashSet是使用HashMap实现的一个没有重复元素的集合.HashSet用法如下: HashSet<String> hashSet ...

  7. 每天一个linux命令:vmstat

    1.命令简介 vmstat(Virtual Memory Statistics 虚拟内存统计) 命令用来显示Linux系统虚拟内存状态,也可以报告关于进程.内存.I/O等系统整体运行状态. 2.用法 ...

  8. [Java] 绕过证书验证调 HTTPS 接口时报 “SSLHandshakeException: DHPublicKey does not comply to algorithm constraints”的解决办法

    作者: zyl910 一.缘由 最近有在对接一个无证书的HTTPS接口时,总是收到"SSLHandshakeException: DHPublicKey does not comply to ...

  9. c# 非调试状态下面执行

    #if !DEBUG                View("ErrorSimple").ExecuteResult(ControllerContext);#endif

  10. Linux如何统计进程的CPU利用率[转]

    0. 为什么写这篇博客 Linux的top或者ps都可以查看进程的cpu利用率,那为什么还需要了解这个细节呢.编写这篇文章呢有如下三个原因: * 希望在脚本中,能够以过”非阻塞”的方式获取进程cpu利 ...