自己制作一个网站,济南网站seo厂家,wordpress动态背景插件,专业定制网红变色杯在之前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中#xff0c;我们讨论了微服务以及如何使用#xff08;RxJava#xff09;的Reactive Extensions编排微服务。 但是#xff0c;如果一项或多项服务由于已被暂停或引发异常而… 在之前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中我们讨论了微服务以及如何使用RxJava的Reactive Extensions编排微服务。 但是如果一项或多项服务由于已被暂停或引发异常而失败该怎么办 在像微服务体系结构这样的分布式系统中正常的情况是远程服务可能会失败因此它们之间的通信应该是容错的并且可以适当地管理网络呼叫中的延迟。 而这正是Hystrix所做的。 Hystrix是一个延迟和容错库旨在隔离对远程系统服务和第三方库的访问点停止级联故障并在不可避免发生故障的复杂分布式系统中实现弹性。 在像微服务这样的分布式体系结构中一个服务可能需要使用其他服务作为依赖项来完成其工作。 应用程序中通过网络或客户端库伸出来并可能导致网络请求的每个点都是失败的根源。 比故障更糟的是这些应用程序还可能导致服务之间的延迟增加。 这给我们带来了另一个大问题假设您正在Tomcat上开发一个服务该服务将打开两个服务的两个连接如果其中一个服务花费的时间比预期的要多得多则您将花费一个线程。 Tomcat池当前请求之一不执行任何操作而是等待一个答案。 如果您的网站流量不高这可能是可以接受的但是如果您的流量很大则所有资源可能会变得饱和并阻塞整个服务器。 Hystrix Wiki提供了这种情况下的模式 避免先前问题的方法是添加一个线程层以将每个依赖项彼此隔离。 因此每个依赖项服务可能包含一个线程池以执行该服务。 在Hystrix中此层由HystricxCommand对象实现因此对外部服务的每次调用都被包装为在不同的线程中执行。 Hystrix Wiki提供了此方案的模式 而且Hystrix还提供其他功能 每个线程都有一个超时因此调用可能不会无限等待响应。 在可行的情况下执行回退以保护用户免受故障的影响。 衡量成功失败客户端抛出的异常超时和线程拒绝并进行监视。 实现断路器模式如果错误百分比超过阈值该模式将在一段时间内自动或手动停止所有对外部服务的请求。 因此让我们从一个非常简单的示例开始 public class HelloWorldCommand extends HystrixCommandString {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.0或Servlet 3.0规范 。 为此只需运行 FutureString 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方法 ObservableString obs new HelloWorldCommand().observe();
obs.subscribe((v) - {System.out.println(onNext: v);
} 但是有时情况可能会出错命令的执行可能会引发异常。 从run方法抛出的所有异常 HystrixBadRequestException除外 均计为失败并触发getFallback和断路器逻辑更多有关断路器。 您不希望将其视为服务故障的任何业务异常例如非法参数都必须包装在HystrixBadRequestException中 。 但是服务故障会怎样 Hystrix可以为我们做什么 总之 Hystrix可以提供两件事 一种在服务失败的情况下执行某些操作的方法。 此方法可能返回空的默认值或存根值或者例如可以调用另一项服务该服务可以完成与失败的服务相同的逻辑。 自动打开和关闭电路的某种逻辑。 倒退 发生异常 HystrixBadRequestException除外时调用的方法是getFallback 。 您可以重写此方法并提供自己的实现。 public class HelloWorldCommand extends HystrixCommandString {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中有一个名为HystrixRequestContext的特殊类。 此类包含状态并管理请求的生命周期。 例如如果您想让Hystrix管理缓存结果或出于日志目的则需要初始化此类。 通常此类在启动业务逻辑之前例如在Servlet Filter中 进行初始化并在处理请求后完成。 让我们使用以前的HelloWorldComand来验证电路断开时是否调用了fallback方法。 public class HelloWorldCommand extends HystrixCommandString {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/watchv gxEPV4kolz0 翻译自: https://www.javacodegeeks.com/2014/09/defend-your-application-with-hystrix.html