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. poj2778(AC 自动机)

    poj2778 题意 构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ? 分析 AC 自动机 + 矩阵快速幂的神题 ,知识点很 ...

  2. 3、Django实战第3天:数据建模

    users modesl.py设计 UserProfile 用户信息 EmailVerifyRecord 验证码 Banner 轮播图 之前我们生成了Django默认的数据表,里面有张表示auth-u ...

  3. ( 转 ) .net 操作 JWT

    GitHub: https://github.com/jwt-dotnet/jwt 1.JWT定义 JWT(Json Web Token)是一种用于双方之间传递安全信息的简洁的.URL安全的表述性声明 ...

  4. [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)

    还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...

  5. Java杂谈6——Java安全模型

    Java语言安全模型是其有别于传统的编程语言的一个很重要的特点,采用一种沙箱模型隔离了Java的运行环境与具体的操作系统,使得Java在网络环境下能够更为安全的运行.理解Java的安全模型,能够帮助我 ...

  6. node.js学习一——什么是node.js

    定义:node.js是运行在服务器端的运用了谷歌v8引擎的javascript运行平台 特点:1. 异步式I/O(非阻塞式I/O) 2. 事件驱动 什么是异步式I/O(非阻塞式I/O)? 要了解什么是 ...

  7. SecureCRT实现跳板机自动登录

    背景: 1.通常运维会开放几个内网的机器能跳转到外网机器进行访问,这样的就是跳板机. 2.比如线上有120.0.0.2这台机器,而内网192.168.1.2这台连接了VPN,能通过SSH登录120.0 ...

  8. sqlserver 调试WINDBG ---troubleshootingsql.com

    https://troubleshootingsql.com/tag/stack-dump/ Debugging that latch timeout Posted on August 26, 201 ...

  9. Step by Step 使用HTML5开发一个星际大战游戏(2)

    HTML5 Canvas Game: 玩家飞船  本系列博文翻译自以下文章 http://blog.sklambert.com/html5-canvas-game-the-player-ship/ L ...

  10. Ado.Net基础拾遗一:读取数据

    从数据库中读取数据: 使用DataReader对象从数据库中读取数据 首先需要添加几个命名空间 //需要添加的命名空间 using System.Configuration; using System ...