1. 回顾

  上文讲解了容错的重要性,以及容错需要实现的功能。

  本文来讲解使用Hystrix实现容错。

2. Hystrix简介

  Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提高系统的可用性与容错性。

  Hystrix主要通过以下几点实现延迟和容错:

  • 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。

    这使用到了设计模式中的“命令模式”。

  • 跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。
  • 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,

    而不是排队等候,从而加速失败判定。

  • 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
  • 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
  • 自我修复:断路器打开一段时间后,会自动进入“半开”状态。断路器打开、关闭、半开的逻辑转换,上文已经详细探讨过,不再赘述。

3. 通用方式整合Hystrix

  > 复制项目 microservice-consumer-movie-ribbon,将 ArtifactId 修改为 microservice-consumer-movie-ribbon-hystrix

  > 添加 hystrix 的依赖

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

  > 在启动类上添加 @EnableCircuitBreaker 或 @EnableHystrix 注解,从而为项目启用断路器支持

package com.itmuch.cloud.microserviceconsumermovieribbonhystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; @SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class MicroserviceConsumerMovieRibbonHystrixApplication { public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonHystrixApplication.class, args);
} @Bean
@LoadBalanced // 实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

  > 修改 MovieController,让其中的findById方法具备容错能力。

package com.itmuch.cloud.microserviceconsumermovieribbonhystrix.controller;

import com.itmuch.cloud.microserviceconsumermovieribbonhystrix.pojo.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class MovieController { private static final Logger LOGGER = LoggerFactory.getLogger(MovieController.class); @Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient; @HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
} @GetMapping("/log-instance")
public void logUserInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
// 打印当前选择的是哪个节点
MovieController.LOGGER.info("{}:{}:{}", serviceInstance.getServiceId(), serviceInstance.getHost(),
serviceInstance.getPort());
} public User findByIdFallback(Long id) {
LOGGER.warn("请求异常,执行回退方式");
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
} }

  > 启动项目 microservice-discovery-eureka

  > 启动项目 microservice-provider-user

  > 启动项目 microservice-consumer-movie-ribbon-hystrix

  > 访问 http://localhost:8010/user/1,获得如下结果,说明可正常访问

  > 停止项目 microservice-provider-user

  > 访问 http://localhost:8010/user/1,获得如下结果,说明当用户微服务不可用时,进入了回退方法

  注意:当请求失败、被拒绝、超时或者断路器打开时,都会进入回退方法。但进入回退方法并不意味着断路器已被打开。

4. Hystrix断路器的状态监控与深入理解

  还记得之前已经为项目引入了Spring Boot Actuator 的依赖,该依赖的作用就是监控应用程序的运行状态。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

  断路器的状态也会暴露在Actuator提供的 /actuator/health 端口中,这样就可以直观地了解断路器的状态。

  但是之前使用的是 Actuator 的默认配置。在默认配置中,/actuator/health 端口只能查看系统的状态,不能查看详细信息,

  因此需要对 Actuator进行进一步配置。

  在 application.yml 中添加如下配置

management:
endpoint:
health:
show-details: always

  > 启动项目 microservice-discovery-eureka

  > 启动项目 microservice-consumer-movie-ribbon-hystrix

  > 访问 http://localhost:8010/user/1,结果如下,说明已执行了回退逻辑,返回了默认用户。

  > 访问 http://localhost:8010/actuator/health,结果如下,此时Hystrix的状态依然是 UP,这是因为我们的失败率还没有达到阈值

    (默认是5秒返回20次失败)

  > 持续快速的访问 http://localhost:8010/user/1,然后访问 http://localhost:8010/actuator/health,此时结果如下

  注意:由上面的测试可以发现——执行回退逻辑并不代表断路器已经打开。请求失败、超时、被拒绝以及断路器打开时都会执行回退逻辑。

5. Hystrix线程隔离策略与传播上下文

  先来阅读一下Hystrix官方Wiki(https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.strategy

  执行

    以下属性控制 HystrixCommand.run() 是如何运行的

  execution.isolation.strategy

    这个属性决定了 HystrixCommand.run() 以哪种隔离策略去执行,下面两种选择中的一个:

    • THREAD(线程隔离):它将在单独的线程上执行,并发请求受线程池中的线程数量的限制。
    • SEMAPHORE(信号量隔离):它将在调用线程上执行,开销相对较小,并发请求收到信号量个数的限制。

  Thread or Semaphore

    默认并且推荐的设置是,运行 HystrixCommand 使用线程隔离(THREAD)HystrixObservableCommand 使用信号量隔离(SEMAPHORE)

    在线程中执行命令有一个除网络超时以外的额外保护层。

    一般来说,只有当调用负载非常高时(每个实例每秒调用数百次)才需要对 HystrixCommand 使用信号量隔离,因为这种场景下

    使用单独线程开销太高,这通常只适用于非网络调用。

  

  了解了Hystrix的隔离策略后,再来看一下 Spring Cloud 官方的文档(http://cloud.spring.io/spring-cloud-static/Finchley.M8/single/spring-cloud.html#_propagating_the_security_context_or_using_spring_scopes

  如果你想传播线程本地的上下文到 @HystrixCommand,默认声明将不会工作,因为它会在线程池中执行命令(在超时的情况下)。

  你可以使用一些配置,让 Hystrix 使用相同的线程,或者直接在注解中让 Hystrix 使用不同的隔离策略。例如:

@HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")
}
)
...

  这也适用于使用 @SessionScope 和 @RequestSession 的情况。你会知道什么时候需要这么做,因为会发生一个运行时异常,

  说它找不到作用域上下文(scoped context)。

  你还可以将 hystrix.shareSecurityContext 属性设置为 true,这样将会自动配置一个 Hystrix 并发策略插件的 hook,这个hook会

  将 SecurityContext 从主线程传输到 Hystrix 的命令。因为 Hystrix 不允许注册多个 Hystrix 策略,所以可以声明 HystrixConcurrencyStrategy

  为一个Spring bean来实现扩展。Spring Cloud会在Spring的上下文中查找你的实现,并将其包装在自己的插件中。

  把Spring Cloud 和 Hystrix 的文档对照阅读,可以帮助理解相关概念。

  • Hystrix的隔离策略有THREAD和SEMAPHORE两种,默认是THREAD。
  • 正常情况下,保持默认即可。
  • 如果发生找不到上下文的运行时异常,可考虑将隔离策略设置为SEMAPHORE。

6. 总结

  本文讲解了Hystrix的整合,对Hystrix断路器的理解及监控,还有Hystrix的隔离策略与传播上下文等。

  下文将讲解Feign使用Hystrix。敬请期待~~~

7. 参考

  周立 --- 《Spring Cloud与Docker微服务架构与实战》

SpringCloud系列十五:使用Hystrix实现容错的更多相关文章

  1. SpringCloud系列十四:实现容错的手段

    1. 回顾 前面已用Eureka实现了微服务的注册与发现,Ribbon实现了客户端侧的负载均衡,Feign实现了声明式的API调用. 2. 实现容错的手段 如果服务提供者响应非常慢,那么消费者对提供者 ...

  2. 跟我学SpringCloud | 第十五篇:微服务利剑之APM平台(一)Skywalking

    目录 SpringCloud系列教程 | 第十五篇:微服务利剑之APM平台(一)Skywalking 1. Skywalking概述 2. Skywalking主要功能 3. Skywalking主要 ...

  3. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  4. 聊聊MySQL的加锁规则《死磕MySQL系列 十五》

    大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...

  5. SpringCloud系列十六:Feign使用Hystrix

    1. 回顾 上文讲解了使用注解@HystrixCommand的fallbackMethod属性实现回退.然而,Feign是以接口形式工作的, 它没有方法体,前文讲解的方式显然不适用与Feign. 事实 ...

  6. 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式

    1.html特殊字符的显示 我们知道html语言和C语言一样也有一些特殊字符,它们是不能正常显示的,必须经过转义,在网上可以查到如何显示这些字符,如下图所示: 上图给了最常用的特殊字符的显示,下面我们 ...

  7. SSE图像算法优化系列十五:YUV/XYZ和RGB空间相互转化的极速实现(此后老板不用再担心算法转到其他空间通道的耗时了)。

    在颜色空间系列1: RGB和CIEXYZ颜色空间的转换及相关优化和颜色空间系列3: RGB和YUV颜色空间的转换及优化算法两篇文章中我们给出了两种不同的颜色空间的相互转换之间的快速算法的实现代码,但是 ...

  8. SpringCloud系列十二:SpringCloudSleuth(SpringCloudSleuth 简介、SpringCloudSleuth 基本配置、数据采集)

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringCloudSleuth 2.具体内容 Sleuth 是一种提供的跟踪服务,也就是说利用 sleuth 技术 ...

  9. SpringCloud系列十:SpringCloudConfig 高级配置(密钥加密处理(JCE)、KeyStore 加密处理、SpringCloudConfig 高可用机制、SpringCloudBus 服务总线)

    1.概念:SpringCloudConfig 高级配置 2.具体内容 在 SpringCloudConfig 之中考虑到所有配置文件都暴露在远程仓库之中的安全性问题,所以提供有安全访问的处理机制,这样 ...

随机推荐

  1. 学习LSM(Linux security module)之四:一个基于LSM的简单沙箱的设计与实现

    嗯!如题,一个简单的基于LSM的沙箱设计.环境是Linux v4.4.28.一个比较新的版本,所以在实现过程中很难找到资料,而且还有各种坑逼,所以大部分的时间都是在看源码,虽然写的很烂,但是感觉收获还 ...

  2. 【2-SAT】Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) D. Innokenty and a Football League

    先反复地扫(不超过n次),把所有可以确定唯一取法的给确定下来. 然后对于剩下的不能确定的,跑2-SAT.输出可行解时,对于a和¬a,如果a所在的强连通分量序号在¬a之前,则取a,否则不取a.如果a和¬ ...

  3. Spark1.4远程调试

    1)首先,我们是在使用spark-submit提交作业时,使用 --driver-java-options ”-Xdebug -Xrunjdwp:transport=dt_socket,server= ...

  4. 数据挖掘经典算法——K-means算法

    算法描述 K-means算法是一种被广泛使用的基于划分的聚类算法,目的是将n个对象会分成k个簇.算法的具体描述如下: 随机选取k个对象作为簇中心: Do 计算所有对象到这k个簇中心的距离,将距离最近的 ...

  5. 数据库问题5-SYS.SYSPROCESSES使用和查找死锁

    http://blog.sina.com.cn/s/blog_62c4727d0100jc5z.html (一)理論部份 sys.sysprocesses (Transact-SQL) http:// ...

  6. Android线程与线程池

    引言 在Android中,几乎完全采用了Java中的线程机制.线程是最小的调度单位,在很多情况下为了使APP更加流程地运行,我们不可能将很多事情都放在主线程上执行,这样会造成严重卡顿(ANR),那么这 ...

  7. webpack-dev-server最简单的应用

    1.安装 npm install webpack-dev-server --save-dev 2.再exports后加多一个对象即可 devServer: { contentBase: ". ...

  8. JS 创建长度为100的数组,数值为角标

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. iOS:二维码的生成

    所谓的二维码就是一个图片,只不过在iOS需要借用<CoreImage/CoreImage.h>来实现,  并且二维码图片是通过CIImage来转成UIImage的.具体步骤如下: // 1 ...

  10. 异常值监测的方法 Tukey test

    参考: https://www.zhihu.com/question/38066650