用Hystrix保护您的应用程序

68747470733a2f2f6e6574666c69782e6769746875622e636f6d2f487973747269782f696d616765732f687973747269782d6c6f676f2d7461676c696e652d3835302e706e67

在之前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中,我们讨论了微服务以及如何使用(RxJava)的Reactive Extensions编排微服务。 但是,如果一项或多项服务由于已被暂停或引发异常而失败,该怎么办? 在像微服务体系结构这样的分布式系统中,正常的情况是远程服务可能会失败,因此它们之间的通信应该是容错的,并且可以适当地管理网络呼叫中的延迟。

而这正是Hystrix所做的。 Hystrix是一个延迟容错库,旨在隔离对远程系统,服务和第三方库的访问点,停止级联故障,并在不可避免发生故障的复杂分布式系统中实现弹性。

在像微服务这样的分布式体系结构中,一个服务可能需要使用其他服务作为依赖项来完成其工作。 应用程序中通过网络或客户端库伸出来并可能导致网络请求的每个点都是失败的根源。 比故障更糟的是,这些应用程序还可能导致服务之间的延迟增加。 这给我们带来了另一个大问题,假设您正在Tomcat上开发一个服务,该服务将打开两个服务的两个连接,如果其中一个服务花费的时间比预期的要多得多,则您将花费​​一个线程。 Tomcat池(当前请求之一)不执行任何操作,而是等待一个答案。 如果您的网站流量不高,这可能是可以接受的,但是如果您的流量很大,则所有资源可能会变得饱和并阻塞整个服务器。

Hystrix Wiki提供了这种情况下的模式:

soa-3-640

避免先前问题的方法是添加一个线程层,以将每个依赖项彼此隔离。 因此,每个依赖项(服务)可能包含一个线程池以执行该服务。 在Hystrix中,此层由HystricxCommand对象实现,因此,对外部服务的每次调用都被包装为在不同的线程中执行。

Hystrix Wiki提供了此方案的模式:

soa-4-isolation-640

而且Hystrix还提供其他功能:

  • 每个线程都有一个超时,因此调用可能不会无限等待响应。
  • 在可行的情况下执行回退,以保护用户免受故障的影响。
  • 衡量成功,失败(客户端抛出的异常),超时和线程拒绝,并进行监视。
  • 实现断路器模式,如果错误百分比超过阈值,该模式将在一段时间内自动或手动停止所有对外部服务的请求。

因此,让我们从一个非常简单的示例开始:

public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String run() throws Exception {return "Hello World";}
}

然后,我们可以使用execute方法以同步方式执行该命令。

new HelloWorldCommand().execute();

尽管此命令是同步的,但它是在其他线程中执行的。 默认情况下, Hystrix为在同一HystrixCommandGroupKey中定义的每个命令创建一个线程池。 在我们的示例中, Hystrix创建一个线程池,该线程池链接到分组到HelloWorld线程池的所有命令。 然后对于每次执行,都会从池中获取一个线程来执行命令。

但是,我们当然可以异步执行命令(完全适合异步JAX-RS 2.0Servlet 3.0规范 )。 为此,只需运行:

Future<String> helloWorldResult = new HelloWorldCommand().queue();
//some more work
Stirng message = helloWorldResult.get();

实际上,同步调用是由Hystrix在内部实现的,它返回新的HelloWorldCommand()。queue()。get();。 内部。

我们已经看到我们可以同步和异步执行命令,但是还有第三种方法是使用RxJava进行反应式执行(您可以在我之前的文章http://www.javacodegeeks.com/2014/07/中了解有关RxJava的更多信息rxjava-java8-java-ee-7-arquillian-bliss.html )。

为此,您只需要调用observe方法:

Observable<String> obs = new HelloWorldCommand().observe();
obs.subscribe((v) -> {System.out.println("onNext: " + v);
}

但是有时情况可能会出错,命令的执行可能会引发异常。 从run()方法抛出的所有异常 HystrixBadRequestException除外 计为失败并触发getFallback()和断路器逻辑(更多有关断路器)。 您不希望将其视为服务故障的任何业务异常(例如非法参数)都必须包装在HystrixBadRequestException中

但是服务故障会怎样, Hystrix可以为我们做什么? 总之, Hystrix可以提供两件事:

  1. 一种在服务失败的情况下执行某些操作的方法。 此方法可能返回空的默认值或存根值,或者例如可以调用另一项服务,该服务可以完成与失败的服务相同的逻辑。
  2. 自动打开和关闭电路的某种逻辑。

倒退

发生异常( HystrixBadRequestException除外)时调用的方法是getFallback() 。 您可以重写此方法并提供自己的实现。

public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String getFallback() {return "Good Bye";}@Overrideprotected String run() throws Exception {//return "Hello World";throw new IllegalArgumentException();}
}

断路器

断路器 r是一种检测故障并避免不断收到相同错误的软件模式。 而且,如果服务是远程的,则可以在不等待TCP连接超时的情况下引发错误。

假设下一个典型示例:系统每秒需要访问数据库100次,但它失败了。 每秒将引发100次相同的错误,并且由于与远程数据库的连接意味着存在TCP连接,因此每个客户端将等待直到TCP超时到期。

因此,如果系统可以检测到服务出现故障并避免客户端在一段时间内发出更多请求,这将非常有用。 这就是断路器的作用。 对于每次执行,请检查电路是否断开(跳闸),这意味着发生了错误,并且请求将不会发送给服务,并且将执行后备逻辑。 但是,如果电路是闭合的,则该请求将被处理并且可以正常工作。

Hystrix维护一个统计数据库,其中包含成功请求与失败请求的数量。 当Hystrix在规定的空闲时间内检测到失败命令的阈值时,它将断开电路,因此将来的请求将能够尽快返回错误,而不必消耗可能处于脱机状态的服务的资源。 但是好消息是, Hystrix还是负责关闭电路的负责人。 经过一段时间后, Hystrix将尝试再次运行传入的请求,如果该请求成功,则它将关闭电路,否则将保持电路断开。

Hystrix网站的下一张图中,您可以看到Hystrix与电路之间的相互作用。

hystrix流程图原始

既然我们已经了解了Hystrix的基础知识,那么让我们看看如何编写测试以检查Hystrix是否按预期工作。

测试前的最后一件事。 在Hystrix中,有一个名为HystrixRequestContext的特殊类。 此类包含状态并管理请求的生命周期。 例如,如果您想让Hystrix管理缓存结果或出于日志目的,则需要初始化此类。 通常,此类在启动业务逻辑之前(例如,在Servlet Filter中 )进行初始化,并在处理请求后完成。

让我们使用以前的HelloWorldComand来验证电路断开时是否调用了fallback方法。

public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String getFallback() {return "Good Bye";}@Overrideprotected String run() throws Exception {return "Hello World";}
}

和测试。 请记住,出于学术目的,我在测试中添加了很多断言。

@Test
public void should_execute_fallback_method_when_circuit_is_open() {//Initialize HystrixRequestContext to be able to get some metricsHystrixRequestContext context = HystrixRequestContext.initializeContext();HystrixCommandMetrics creditCardMetrics = HystrixCommandMetrics.getInstance(HystrixCommandKey.Factory.asKey(HelloWorldRestCommand.class.getSimpleName()));//We use Archaius to set the circuit as closed.ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.forceOpen", false);String successMessage = new HelloWorldRestCommand().execute();assertThat(successMessage, is("Hello World"));//We use Archaius to open the circuitConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.forceOpen", true);String failMessage = new HelloWorldRestCommand().execute();assertThat(failMessage, is("Good Bye"));//Prints Request => HelloWorldRestCommand[SUCCESS][19ms], HelloWorldRestCommand[SHORT_CIRCUITED, FALLBACK_SUCCESS][0ms] System.out.println("Request => " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());assertThat(creditCardMetrics.getHealthCounts().getTotalRequests(), is(2));assertThat(creditCardMetrics.getHealthCounts().getErrorCount(), is(1));}

这是一个非常简单的示例,因为execute方法和fallback方法非常简单,但是如果您认为execute方法可能包含复杂的逻辑,而fallback方法也可能非常复杂(例如,从另一台服务器检索数据,则生成某种存根数据,…),然后编写集成或功能测试以验证所有这些有意义的流程。 请记住,有时您的后备逻辑可能取决于当前用户或其他用户的先前调用。

Hystrix还提供其他功能,例如兑现结果,因此在同一HystrixRequestContext中已经执行的任何命令可以返回缓存结果( https://github.com/Netflix/Hystrix/wiki/How-To-Use#Caching )。 它提供的另一个功能是折叠。 它支持将请求自动批处理为单个HystrixCommand实例执行。 它可以使用批处理大小和时间作为执行批处理的触发器。

如您所见, Hystrix是一个非常简单但功能强大的库,如果您的应用程序调用外部服务,则应考虑这一点。

我们不断学习,

亚历克斯


唱一首歌,你是钢琴家,今晚唱一首歌,好吧,我们都在想一个旋律,而且你让我们感觉很好(钢琴家– Billy Joel)

音乐: https : //www.youtube.com/watch?v = gxEPV4kolz0

翻译自: https://www.javacodegeeks.com/2014/09/defend-your-application-with-hystrix.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

若依 从下载到成功运行及打包

官网&#xff1a;http://www.ruoyi.vip/ 目录 一、下载并运行项目 二、关于 若依 接口地址配置 2.1 若依的跨域代理介绍 2.2 配置跨域代理&#xff0c;调用后台接口 2.2.1 配置 后台 ip 地址 2.2.2 页面报“系统接口404”错误 三、打包配置 3.1 打包之后静态资源404…

uniAPP小程序 子组件使用watch不生效,H5正常,小程序不正常(其实是子组件model选项的问题)

第一次用 uniapp 写小程序&#xff0c;还是遇到挺多问题的。写了一个下拉多选组件&#xff0c;发现同样的代码&#xff0c;在H5上运行效果正常&#xff0c;在小程序上压根不走 watch 。 uniapp官网&#xff1a;【全局配置 | uni-app官网】 看文档 watch 是支持H5、小程序的&…

jQuery EasyUI/TopJUI创建日期时间输入框

jQuery EasyUI/TopJUI创建日期时间输入框 日期时间输入框组件 HTML 和日期输入框类似&#xff0c;日期时间输入框允许用户选择日期和指定的时间并按照指定的输出格式显示。相比日期输入框&#xff0c;它在下拉面板中添加了一个时间微调器。 <div class"topjui-containe…

table 设置边框

本文引自&#xff1a;https://www.cnblogs.com/leona-d/p/6125896.html 示例代码&#xff1a; <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width…

uniapp小程序 设置自定义导航栏

如下截图&#xff0c;通过 wx.getSystemInfoSync 计算得到的整个导航栏高度&#xff0c;其实是有3个部分的&#xff1a; 黄色&#xff1a;状态栏高度&#xff0c;uniapp文档中有给出&#xff1b;红色&#xff1a;胶囊高度&#xff0c;可以计算得出&#xff1b;绿色&#xff1a;…

Akka Notes –演员记录和测试

在前两部分&#xff08; 一 &#xff0c; 二 &#xff09;中&#xff0c;我们简要讨论了Actor以及消息传递的工作方式。 在这一部分中&#xff0c;让我们看一下如何修复并记录我们的TeacherActor 。 概括 这就是我们上一部分中的Actor的样子&#xff1a; class TeacherActor …

vue笔记(二)Vue-class与style、事件、计算属性、数据监听、指令+自定义指令、过滤器

vue官网 一 、class、style操作 二、事件 三、计算属性 四、数据监听、观测 五、指令自定义指令 六、过滤器 一 、class、style操作 官网 1. class使用&#xff1a; &#xff08;1&#xff09;v-bind:class“数据|属性|变量|表达式” &#xff08;2&#xff09;v-bind:class“…

Nsum问题

题目 题解 暴力法 class Solution:def fourSum(self, nums: List[int], target: int) -> List[List[int]]:if len(nums) < 4:return []nums.sort()N len(nums)res []for i in range(N-3):for j in range(i1, N-2):for k in range(j1, N-1):for m in range(k1, N):tmp…

js笔记(一)js基础、程序结构、函数

大标题小节一、js 基础1. javascript的组成&#xff1b;2. 运行js&#xff1b;3. 打印信息&#xff1b;4. 关键字var&#xff1b;5. js中的数据类型&#xff1b;6. NaN&#xff08;not a number&#xff09;&#xff1b;7. js运算符&#xff1b;8. 数据类型转换&#xff1b;9. …

DB2 9 底子(730 考试)认证指南,第 3 局部: 拜访 DB2 数据(3)

建树第一个数据库First Steps在 DB2 的安顿进程中&#xff0c;会表示 First Steps 面板&#xff0c;它答运用户生成要操作的示例数据库&#xff1a; 选择 Database Creation 选项将表示一个附加菜单&#xff0c;可以建树 SAMPLE 数据库。 大大都用户希冀建树 SAMPLE 数据库并运…

新的自定义控件:TaskProgressView

我已经编写了一个新的自定义控件&#xff0c;并将其提交到ControlsFX项目。 这是一个高度专业的控件&#xff0c;用于显示后台任务&#xff0c;其当前状态和进度的列表。 这实际上是我为ControlsFX编写的第一个控件&#xff0c;只是出于乐趣的考虑&#xff0c;这意味着我自己没…

js笔记(三)ES5、ES5新增的数组的方法、字符串的方法、字符编码、对象的序列化和反序列化、bind

数组方法、字符串方法总结 大目录小目录一、ES5严格模式1. 严格模式&#xff1b;2. 严格模式的行为变更&#xff1b;二、ES5新增的数组的方法1. 判断是否为数组&#xff1a;Array.isArray()&#xff1b;2. 判断数组中是否存在某个值&#xff1a;indexOf(data, start)、lastInd…

SVG入门

1、简介 使用xml描述的矢量文件。 2、兼容性 https://caniuse.com/#searchsvg 3、使用方式 &#xff08;1&#xff09;浏览器直接打开 &#xff08;2&#xff09;html中使用img引用 <p><img src"simple.svg" width"50" height"50"…

js 值和引用

1、概述 简单值&#xff08;基本类型&#xff09;通过值复制的方式来赋值/传递。 复合值&#xff08;对象&#xff09;通过引用复制的方式来赋值/传递。 <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><title…

js笔记(六)事件、正则

数组方法、字符串方法总结 大标题小节一、事件1.1 事件&#xff1b;1.2 事件对象&#xff1b;1.3 键盘事件的keyCode&#xff1b;1.4 关于鼠标的尺寸&#xff1b;1.5 事件冒泡&#xff1b;1.6 事件的默认行为&#xff1b;1.7 事件监听&#xff1b;1.8 事件委托&#xff08;事件…

神州泰岳2050万元收买并增资奇点国际

网易科技讯 3月7日消息&#xff0c;神州泰岳来日诰日颁布发表关照公告&#xff0c;将经由股权让渡体例共付出1450万元股权让渡款获得奇点国际100%股权&#xff0c;同时神州泰岳与邵起明分别出资600万元、200万元对奇点国际举行增资。本次增资后&#xff0c;奇点国际注册资金增进…

拯救你丢失的精度——BigInteger和BigDecimal类(入门)

第三阶段 JAVA常见对象的学习 BigInteger和BigDecimal类 BigInteger类 (一) 构造方法&#xff1a; //针对超过整数范围的运算(整数最大值&#xff1a;2147483647) BigInteger(String val) (二) 常用方法&#xff1a; //加 public BigInteger add(BigInteger val) //减 public…

vue笔记(四)注册组件,路由,vuex

官网 一、项目中的组件注册 二、路由 三、vuex 一、项目中的组件注册 1. 全局 import Loading from /components/loading;//封装的loading组件 Vue.component(Loading,Loading);2. 局部 <loading/>important loading from ./components/loadingcomponents:{loading}二…

#102030:在30天内运行20 10K,庆祝Java 20年

1995年5月23日是技术史上的重要时刻。 业界似乎并没有意识到当天发布的语言会在未来几年内完全改变技术的格局。 Java将在今年的同一天庆祝20岁生日。 Java 20年&#xff0c;哇&#xff01; 回顾20年前的存储器时代&#xff0c;思考一下Java的发明时间/方式。 万维网专用于精…

vue笔记(一)基本使用、数据检测

vue 官网 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。 一、基本使用 二、数据检测 一、Vue的思想 MVC【参考 nd的博客园】&#xff1a; 名称描述M&#xff08;…